wormhole-circle-integration/evm/forge-scripts/submit_testnet_registration...

120 lines
3.7 KiB
Solidity

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import "forge-std/console.sol";
import {ICircleIntegration} from "../src/interfaces/ICircleIntegration.sol";
import {IWormhole} from "../src/interfaces/IWormhole.sol";
contract ContractScript is Script {
// Circle integration
ICircleIntegration integration;
// Wormhole
IWormhole wormhole;
// Circle integration governance
bytes32 constant GOVERNANCE_MODULE = 0x000000000000000000000000000000436972636c65496e746567726174696f6e;
uint8 constant GOVERNANCE_REGISTER_EMITTER_AND_DOMAIN = 2;
function setUp() public {
// Circle integration
integration = ICircleIntegration(vm.envAddress("CIRCLE_INTEGRATION_PROXY"));
// wormhole
wormhole = IWormhole(vm.envAddress("RELEASE_WORMHOLE_ADDRESS"));
}
function doubleKeccak256(bytes memory body) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(keccak256(body)));
}
function encodeObservation(IWormhole.VM memory wormholeMessage) public pure returns (bytes memory) {
return abi.encodePacked(
wormholeMessage.timestamp,
wormholeMessage.nonce,
wormholeMessage.emitterChainId,
wormholeMessage.emitterAddress,
wormholeMessage.sequence,
wormholeMessage.consistencyLevel,
wormholeMessage.payload
);
}
function signObservation(uint256 guardian, IWormhole.VM memory wormholeMessage)
public
view
returns (bytes memory)
{
require(guardian != 0, "devnetGuardian is zero address");
bytes memory body = encodeObservation(wormholeMessage);
// Sign the hash with the devnet guardian private key
IWormhole.Signature[] memory sigs = new IWormhole.Signature[](1);
(sigs[0].v, sigs[0].r, sigs[0].s) = vm.sign(guardian, doubleKeccak256(body));
sigs[0].guardianIndex = 0;
return abi.encodePacked(
uint8(1),
wormhole.getCurrentGuardianSetIndex(),
uint8(sigs.length),
sigs[0].guardianIndex,
sigs[0].r,
sigs[0].s,
sigs[0].v - 27,
body
);
}
function makeRegistrationObservation(
bytes memory decree
) internal view returns (IWormhole.VM memory message) {
message.timestamp = uint32(block.timestamp);
message.nonce = 0;
message.emitterChainId = wormhole.governanceChainId();
message.emitterAddress = wormhole.governanceContract();
message.sequence = wormhole.nextSequence(msg.sender);
message.consistencyLevel = 1;
message.payload = abi.encodePacked(
GOVERNANCE_MODULE,
GOVERNANCE_REGISTER_EMITTER_AND_DOMAIN,
uint16(vm.envUint("TARGET_CHAIN")),
decree
);
}
function generateRegistrationVaa() internal returns (bytes memory vaa) {
IWormhole.VM memory message = makeRegistrationObservation(
abi.encodePacked(
uint16(vm.envUint("FOREIGN_CHAIN")),
bytes32(vm.envBytes32("FOREIGN_EMITTER")),
uint32(vm.envUint("FOREIGN_DOMAIN"))
)
);
// sign the governance message with the signer key
vaa = signObservation(
uint256(vm.envBytes32("SIGNER_KEY")),
message
);
}
function submitRegistrationVaa() internal {
integration.registerEmitterAndDomain(generateRegistrationVaa());
}
function run() public {
// begin sending transactions
vm.startBroadcast();
// query registration vaa
submitRegistrationVaa();
// finished
vm.stopBroadcast();
}
}