tokenbridge: implement new governance packet spec

Change-Id: Iee4b596b6a8ca9dfc9c6ee8c6188a4083a05edeb
This commit is contained in:
valentin 2021-07-26 15:10:16 +02:00 committed by Hendrik Hofstadt
parent c819165d5c
commit 14e892300c
3 changed files with 57 additions and 21 deletions

View File

@ -20,17 +20,21 @@ import "../interfaces/IWormhole.sol";
contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade { contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
using BytesLib for bytes; using BytesLib for bytes;
// "TokenBridge" (left padded)
bytes32 constant module = 0x000000000000000000000000000000000000000000546f6b656e427269646765;
// Execute a RegisterChain governance message // Execute a RegisterChain governance message
function registerChain(bytes memory encodedVM) public { function registerChain(bytes memory encodedVM) public {
(IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM); (IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
require(valid, reason); require(valid, reason);
setGovernanceActionConsumed(vm.hash); setGovernanceActionConsumed(vm.hash);
BridgeStructs.RegisterChain memory chain = parseRegisterChain(vm.payload); BridgeStructs.RegisterChain memory chain = parseRegisterChain(vm.payload);
setBridgeImplementation(chain.chainID, chain.emitterAddress); require(chain.chainId == chainId() || chain.chainId == 0, "invalid chain id");
setBridgeImplementation(chain.emitterChainID, chain.emitterAddress);
} }
// Execute a UpgradeContract governance message // Execute a UpgradeContract governance message
@ -42,7 +46,7 @@ contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
BridgeStructs.UpgradeContract memory implementation = parseUpgrade(vm.payload); BridgeStructs.UpgradeContract memory implementation = parseUpgrade(vm.payload);
require(implementation.chainID == chainId(), "wrong chain id"); require(implementation.chainId == chainId(), "wrong chain id");
upgradeImplementation(address(uint160(uint256(implementation.newContract)))); upgradeImplementation(address(uint160(uint256(implementation.newContract))));
} }
@ -85,34 +89,51 @@ contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
function parseRegisterChain(bytes memory encoded) public pure returns(BridgeStructs.RegisterChain memory chain) { function parseRegisterChain(bytes memory encoded) public pure returns(BridgeStructs.RegisterChain memory chain) {
uint index = 0; uint index = 0;
chain.payloadID = encoded.toUint8(index); // governance header
chain.module = encoded.toBytes32(index);
index += 32;
require(chain.module == module, "invalid RegisterChain: wrong module");
chain.action = encoded.toUint8(index);
index += 1; index += 1;
require(chain.action == 1, "invalid RegisterChain: wrong action");
require(chain.payloadID == 3, "invalid RegisterChain"); chain.chainId = encoded.toUint16(index);
index += 2;
chain.chainID = encoded.toUint16(index); // payload
chain.emitterChainID = encoded.toUint16(index);
index += 2; index += 2;
chain.emitterAddress = encoded.toBytes32(index); chain.emitterAddress = encoded.toBytes32(index);
index += 32; index += 32;
require(encoded.length == index, "invalid RegisterChain"); require(encoded.length == index, "invalid RegisterChain: wrong length");
} }
function parseUpgrade(bytes memory encoded) public pure returns(BridgeStructs.UpgradeContract memory chain) { function parseUpgrade(bytes memory encoded) public pure returns(BridgeStructs.UpgradeContract memory chain) {
uint index = 0; uint index = 0;
chain.payloadID = encoded.toUint8(index); // governance header
chain.module = encoded.toBytes32(index);
index += 32;
require(chain.module == module, "invalid UpgradeContract: wrong module");
chain.action = encoded.toUint8(index);
index += 1; index += 1;
require(chain.action == 2, "invalid UpgradeContract: wrong action");
require(chain.payloadID == 4, "invalid UpgradeContract"); chain.chainId = encoded.toUint16(index);
chain.chainID = encoded.toUint16(index);
index += 2; index += 2;
// payload
chain.newContract = encoded.toBytes32(index); chain.newContract = encoded.toBytes32(index);
index += 32; index += 32;
require(encoded.length == index, "invalid UpgradeContract"); require(encoded.length == index, "invalid UpgradeContract: wrong length");
} }
} }

View File

@ -37,19 +37,29 @@ contract BridgeStructs {
} }
struct RegisterChain { struct RegisterChain {
// PayloadID uint8 = 3 // Governance Header
uint8 payloadID; // module: "TokenBridge" left-padded
bytes32 module;
// governance action: 1
uint8 action;
// governance paket chain id: this or 0
uint16 chainId;
// Chain ID // Chain ID
uint16 chainID; uint16 emitterChainID;
// Emitter address. Left-zero-padded if shorter than 32 bytes // Emitter address. Left-zero-padded if shorter than 32 bytes
bytes32 emitterAddress; bytes32 emitterAddress;
} }
struct UpgradeContract { struct UpgradeContract {
// PayloadID uint8 = 4 // Governance Header
uint8 payloadID; // module: "TokenBridge" left-padded
// Chain ID bytes32 module;
uint16 chainID; // governance action: 2
uint8 action;
// governance paket chain id
uint16 chainId;
// Address of the new contract // Address of the new contract
bytes32 newContract; bytes32 newContract;
} }

View File

@ -79,7 +79,10 @@ contract("Bridge", function () {
const accounts = await web3.eth.getAccounts(); const accounts = await web3.eth.getAccounts();
let data = [ let data = [
"0x03", "0x",
"000000000000000000000000000000000000000000546f6b656e427269646765",
"01",
"0000",
web3.eth.abi.encodeParameter("uint16", testForeignChainId).substring(2 + (64 - 4)), web3.eth.abi.encodeParameter("uint16", testForeignChainId).substring(2 + (64 - 4)),
web3.eth.abi.encodeParameter("bytes32", testForeignBridgeContract).substring(2), web3.eth.abi.encodeParameter("bytes32", testForeignBridgeContract).substring(2),
].join('') ].join('')
@ -121,7 +124,9 @@ contract("Bridge", function () {
const mock = await MockBridgeImplementation.new(); const mock = await MockBridgeImplementation.new();
let data = [ let data = [
"0x04", "0x",
"000000000000000000000000000000000000000000546f6b656e427269646765",
"02",
web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)), web3.eth.abi.encodeParameter("uint16", testChainId).substring(2 + (64 - 4)),
web3.eth.abi.encodeParameter("address", mock.address).substring(2), web3.eth.abi.encodeParameter("address", mock.address).substring(2),
].join('') ].join('')