Skip to content

Commit 33f5b8a

Browse files
authored
[eth] Remove ownership entirely in favor of governance (#405)
1 parent c3461e5 commit 33f5b8a

File tree

15 files changed

+165
-464
lines changed

15 files changed

+165
-464
lines changed

ethereum/.env.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ PYTHNET_CHAIN_ID= # 0x1a
1919
PYTHNET_EMITTER= # 0xa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6
2020
GOVERNANCE_CHAIN_ID= # 0x1
2121
GOVERNANCE_EMITTER= # 0x63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385
22+
GOVERNANCE_INITIAL_SEQUENCE=0 # This is optional and default is 0
2223
SINGLE_UPDATE_FEE_IN_WEI=0

ethereum/contracts/pyth/Pyth.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth {
1717
address wormhole,
1818
uint16[] calldata dataSourceEmitterChainIds,
1919
bytes32[] calldata dataSourceEmitterAddresses,
20+
uint16 governanceEmitterChainId,
21+
bytes32 governanceEmitterAddress,
22+
uint64 governanceInitialSequence,
2023
uint validTimePeriodSeconds,
2124
uint singleUpdateFeeInWei
2225
) internal {
@@ -41,6 +44,15 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth {
4144
_state.validDataSources.push(ds);
4245
}
4346

47+
{
48+
PythInternalStructs.DataSource memory ds = PythInternalStructs
49+
.DataSource(governanceEmitterChainId, governanceEmitterAddress);
50+
PythSetters.setGovernanceDataSource(ds);
51+
PythSetters.setLastExecutedGovernanceSequence(
52+
governanceInitialSequence
53+
);
54+
}
55+
4456
PythSetters.setValidTimePeriodSeconds(validTimePeriodSeconds);
4557
PythSetters.setSingleUpdateFeeInWei(singleUpdateFeeInWei);
4658
}

ethereum/contracts/pyth/PythUpgradable.sol

Lines changed: 9 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ contract PythUpgradable is
2424
address wormhole,
2525
uint16[] calldata dataSourceEmitterChainIds,
2626
bytes32[] calldata dataSourceEmitterAddresses,
27+
uint16 governanceEmitterChainId,
28+
bytes32 governanceEmitterAddress,
29+
uint64 governanceInitialSequence,
2730
uint validTimePeriodSeconds,
2831
uint singleUpdateFeeInWei
2932
) public initializer {
@@ -34,85 +37,23 @@ contract PythUpgradable is
3437
wormhole,
3538
dataSourceEmitterChainIds,
3639
dataSourceEmitterAddresses,
40+
governanceEmitterChainId,
41+
governanceEmitterAddress,
42+
governanceInitialSequence,
3743
validTimePeriodSeconds,
3844
singleUpdateFeeInWei
3945
);
40-
}
41-
42-
/// Privileged function to specify additional data sources in the contract
43-
function addDataSource(uint16 chainId, bytes32 emitter) public onlyOwner {
44-
PythInternalStructs.DataSource memory ds = PythInternalStructs
45-
.DataSource(chainId, emitter);
46-
require(
47-
!PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress),
48-
"Data source already added"
49-
);
50-
51-
_state.isValidDataSource[hashDataSource(ds)] = true;
52-
_state.validDataSources.push(ds);
53-
}
54-
55-
/// Privileged fucntion to remove the specified data source. Assumes _state.validDataSources has no duplicates.
56-
function removeDataSource(
57-
uint16 chainId,
58-
bytes32 emitter
59-
) public onlyOwner {
60-
PythInternalStructs.DataSource memory ds = PythInternalStructs
61-
.DataSource(chainId, emitter);
62-
require(
63-
PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress),
64-
"Data source not found, not removing"
65-
);
66-
67-
_state.isValidDataSource[hashDataSource(ds)] = false;
68-
69-
for (uint i = 0; i < _state.validDataSources.length; ++i) {
70-
// Find the source to remove
71-
if (
72-
_state.validDataSources[i].chainId == ds.chainId ||
73-
_state.validDataSources[i].emitterAddress == ds.emitterAddress
74-
) {
75-
// Copy last element to overwrite the target data source
76-
_state.validDataSources[i] = _state.validDataSources[
77-
_state.validDataSources.length - 1
78-
];
79-
// Remove the last element we just preserved
80-
_state.validDataSources.pop();
81-
82-
break;
83-
}
84-
}
85-
}
86-
87-
/// Privileged function to update the price update fee
88-
function updateSingleUpdateFeeInWei(uint newFee) public onlyOwner {
89-
PythSetters.setSingleUpdateFeeInWei(newFee);
90-
}
91-
92-
/// Privileged function to update the valid time period for a price.
93-
function updateValidTimePeriodSeconds(
94-
uint newValidTimePeriodSeconds
95-
) public onlyOwner {
96-
PythSetters.setValidTimePeriodSeconds(newValidTimePeriodSeconds);
97-
}
9846

99-
// Privileged function to update the governance emitter
100-
function updateGovernanceDataSource(
101-
uint16 chainId,
102-
bytes32 emitter,
103-
uint64 sequence
104-
) public onlyOwner {
105-
PythInternalStructs.DataSource memory ds = PythInternalStructs
106-
.DataSource(chainId, emitter);
107-
PythSetters.setGovernanceDataSource(ds);
108-
PythSetters.setLastExecutedGovernanceSequence(sequence);
47+
renounceOwnership();
10948
}
11049

11150
/// Ensures the contract cannot be uninitialized and taken over.
11251
/// @custom:oz-upgrades-unsafe-allow constructor
11352
constructor() initializer {}
11453

11554
// Only allow the owner to upgrade the proxy to a new implementation.
55+
// The contract has no owner so this function will always revert
56+
// but UUPSUpgradeable expects this method to be implemented.
11657
function _authorizeUpgrade(address) internal override onlyOwner {}
11758

11859
function pythUpgradableMagic() public pure returns (uint32) {

ethereum/forge-test/utils/PythTestUtils.t.sol

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,11 @@ abstract contract PythTestUtils is Test, WormholeTestUtils {
3939
wormhole,
4040
emitterChainIds,
4141
emitterAddresses,
42-
60, // Valid time period in seconds
43-
1 // single update fee in wei
44-
);
45-
46-
pyth.updateGovernanceDataSource(
4742
GOVERNANCE_EMITTER_CHAIN_ID,
4843
GOVERNANCE_EMITTER_ADDRESS,
49-
0
44+
0, // Initial governance sequence
45+
60, // Valid time period in seconds
46+
1 // single update fee in wei
5047
);
5148

5249
return address(pyth);

ethereum/migrations/prod-receiver/10_pyth_enable_governance.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

ethereum/migrations/prod-receiver/3_deploy_pyth.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,34 +15,36 @@ const emitterAddresses = [
1515
process.env.SOLANA_EMITTER,
1616
process.env.PYTHNET_EMITTER,
1717
];
18+
const governanceChainId = process.env.GOVERNANCE_CHAIN_ID;
19+
const governanceEmitter = process.env.GOVERNANCE_EMITTER;
20+
// Default value for this field is 0
21+
const governanceInitialSequence = Number(
22+
process.env.GOVERNANCE_INITIAL_SEQUENCE ?? "0"
23+
);
24+
1825
const validTimePeriodSeconds = Number(process.env.VALID_TIME_PERIOD_SECONDS);
1926
const singleUpdateFeeInWei = Number(process.env.SINGLE_UPDATE_FEE_IN_WEI);
2027

2128
console.log("emitterChainIds: " + emitterChainIds);
2229
console.log("emitterAddresses: " + emitterAddresses);
30+
console.log("governanceEmitter: " + governanceEmitter);
31+
console.log("governanceChainId: " + governanceChainId);
32+
console.log("governanceInitialSequence: " + governanceInitialSequence);
2333
console.log("validTimePeriodSeconds: " + validTimePeriodSeconds);
2434
console.log("singleUpdateFeeInWei: " + singleUpdateFeeInWei);
2535

2636
module.exports = async function (deployer, network) {
27-
const cluster = process.env.CLUSTER;
28-
const chainName = process.env.WORMHOLE_CHAIN_NAME;
29-
30-
assert(cluster !== undefined && chainName !== undefined);
31-
32-
const wormholeBridgeAddress =
33-
CONTRACTS[cluster.toUpperCase()][chainName].core;
34-
assert(wormholeBridgeAddress !== undefined);
35-
36-
console.log("Wormhole bridge address: " + wormholeBridgeAddress);
37-
3837
// Deploy the proxy. This will return an instance of PythUpgradable,
3938
// with the address field corresponding to the fronting ERC1967Proxy.
4039
let proxyInstance = await deployProxy(
4140
PythUpgradable,
4241
[
43-
wormholeBridgeAddress,
42+
(await WormholeReceiver.deployed()).address,
4443
emitterChainIds,
4544
emitterAddresses,
45+
governanceChainId,
46+
governanceEmitter,
47+
governanceInitialSequence,
4648
validTimePeriodSeconds,
4749
singleUpdateFeeInWei,
4850
],

ethereum/migrations/prod/11_pyth_renounce_ownership.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

ethereum/migrations/prod/2_deploy_pyth.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,21 @@ const emitterAddresses = [
1515
process.env.SOLANA_EMITTER,
1616
process.env.PYTHNET_EMITTER,
1717
];
18+
const governanceChainId = process.env.GOVERNANCE_CHAIN_ID;
19+
const governanceEmitter = process.env.GOVERNANCE_EMITTER;
20+
// Default value for this field is 0
21+
const governanceInitialSequence = Number(
22+
process.env.GOVERNANCE_INITIAL_SEQUENCE ?? "0"
23+
);
24+
1825
const validTimePeriodSeconds = Number(process.env.VALID_TIME_PERIOD_SECONDS);
1926
const singleUpdateFeeInWei = Number(process.env.SINGLE_UPDATE_FEE_IN_WEI);
2027

2128
console.log("emitterChainIds: " + emitterChainIds);
2229
console.log("emitterAddresses: " + emitterAddresses);
30+
console.log("governanceEmitter: " + governanceEmitter);
31+
console.log("governanceChainId: " + governanceChainId);
32+
console.log("governanceInitialSequence: " + governanceInitialSequence);
2333
console.log("validTimePeriodSeconds: " + validTimePeriodSeconds);
2434
console.log("singleUpdateFeeInWei: " + singleUpdateFeeInWei);
2535

@@ -43,6 +53,9 @@ module.exports = async function (deployer, network) {
4353
wormholeBridgeAddress,
4454
emitterChainIds,
4555
emitterAddresses,
56+
governanceChainId,
57+
governanceEmitter,
58+
governanceInitialSequence,
4659
validTimePeriodSeconds,
4760
singleUpdateFeeInWei,
4861
],

ethereum/migrations/prod/9_pyth_enable_governance.js

Lines changed: 0 additions & 25 deletions
This file was deleted.

ethereum/migrations/test/10_pyth_renounce_ownership.js

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)