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 {
using BytesLib for bytes;
// "TokenBridge" (left padded)
bytes32 constant module = 0x000000000000000000000000000000000000000000546f6b656e427269646765;
// Execute a RegisterChain governance message
function registerChain(bytes memory encodedVM) public {
(IWormhole.VM memory vm, bool valid, string memory reason) = verifyGovernanceVM(encodedVM);
require(valid, reason);
setGovernanceActionConsumed(vm.hash);
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
@ -42,7 +46,7 @@ contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
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))));
}
@ -85,34 +89,51 @@ contract BridgeGovernance is BridgeGetters, BridgeSetters, ERC1967Upgrade {
function parseRegisterChain(bytes memory encoded) public pure returns(BridgeStructs.RegisterChain memory chain) {
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;
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;
chain.emitterAddress = encoded.toBytes32(index);
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) {
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;
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;
// payload
chain.newContract = encoded.toBytes32(index);
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 {
// PayloadID uint8 = 3
uint8 payloadID;
// Governance Header
// module: "TokenBridge" left-padded
bytes32 module;
// governance action: 1
uint8 action;
// governance paket chain id: this or 0
uint16 chainId;
// Chain ID
uint16 chainID;
uint16 emitterChainID;
// Emitter address. Left-zero-padded if shorter than 32 bytes
bytes32 emitterAddress;
}
struct UpgradeContract {
// PayloadID uint8 = 4
uint8 payloadID;
// Chain ID
uint16 chainID;
// Governance Header
// module: "TokenBridge" left-padded
bytes32 module;
// governance action: 2
uint8 action;
// governance paket chain id
uint16 chainId;
// Address of the new contract
bytes32 newContract;
}

View File

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