add EVM contract for batched VAA development

This commit is contained in:
justinschuldt 2022-08-12 07:43:37 -05:00 committed by Justin Schuldt
parent 99fb46d549
commit d7b102df70
8 changed files with 182 additions and 1 deletions

View File

@ -53,7 +53,7 @@ spec:
command:
- /bin/sh
- -c
- "npm run migrate && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_bsc_chain.js && npx truffle exec scripts/register_algo_chain.js && nc -lkp 2000 0.0.0.0"
- "npm run migrate && npm run deploy-batched-vaa-sender && npx truffle exec scripts/deploy_test_token.js && npx truffle exec scripts/register_solana_chain.js && npx truffle exec scripts/register_terra_chain.js && npx truffle exec scripts/register_terra2_chain.js && npx truffle exec scripts/register_bsc_chain.js && npx truffle exec scripts/register_algo_chain.js && nc -lkp 2000 0.0.0.0"
readinessProbe:
periodSeconds: 1
failureThreshold: 300

View File

@ -57,3 +57,13 @@ wormhole/ethereum $ ../scripts/install-foundry
```
The installer script installs foundry and the appropriate solc version to build the contracts.
### Batched VAAs
To send a transaction that will create multiple VAAs, invoke the `sendMultipleMessages` method of [ethereum/contracts/mock/MockBatchedVAASender.sol](./contracts/mock/MockBatchedVAASender.sol) with the truffle script:
npx truffle exec scripts/send_batched_vaa.js
or invoke the same script in the tilt devnet:
minikube kubectl -- exec -n wormhole eth-devnet-0 -c tests -- npx truffle exec scripts/send_batched_vaa.js

View File

@ -0,0 +1,53 @@
// contracts/mock/MockBatchedVAASender.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../libraries/external/BytesLib.sol";
import "../interfaces/IWormhole.sol";
contract MockBatchedVAASender {
using BytesLib for bytes;
address wormholeCoreAddress;
function sendMultipleMessages(
uint32 nonce,
bytes memory payload,
uint8 consistencyLevel
)
public
payable
returns (
uint64 messageSequence0,
uint64 messageSequence1,
uint64 messageSequence2
)
{
messageSequence0 = wormholeCore().publishMessage{value: msg.value}(
nonce,
payload,
consistencyLevel
);
messageSequence1 = wormholeCore().publishMessage{value: msg.value}(
nonce,
payload,
consistencyLevel
);
messageSequence2 = wormholeCore().publishMessage{value: msg.value}(
nonce,
payload,
consistencyLevel
);
}
function wormholeCore() private view returns (IWormhole) {
return IWormhole(wormholeCoreAddress);
}
function setup(address _wormholeCore) public {
wormholeCoreAddress = _wormholeCore;
}
}

View File

@ -0,0 +1,15 @@
require('dotenv').config({ path: "../.env" });
const Wormhole = artifacts.require("Wormhole");
const MockBatchedVAASender = artifacts.require("MockBatchedVAASender");
module.exports = async function (deployer, network, accounts) {
await deployer.deploy(MockBatchedVAASender)
const contract = new web3.eth.Contract(MockBatchedVAASender.abi, MockBatchedVAASender.address);
await contract.methods.setup(
Wormhole.address
).send({from: accounts[0]})
};

View File

@ -25,6 +25,7 @@
"deploy-bridge-implementation-only": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --f 6 --to 6",
"deploy-read-only": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --f 1 --to 2",
"deploy_weth9": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --f 9",
"deploy-batched-vaa-sender": "mkdir -p build/contracts && cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/ && truffle migrate --f 10 --to 10",
"verify": "patch -u -f node_modules/truffle-plugin-verify/constants.js -i truffle-verify-constants.patch; truffle run verify $npm_config_module@$npm_config_contract_address --network $npm_config_network",
"verify-token": "patch -u -f node_modules/truffle-plugin-verify/constants.js -i truffle-verify-constants.patch; truffle run verify BridgeToken@$npm_config_contract_address --forceConstructorArgs string:$npm_config_constructor_args --network $npm_config_network",
"abigen": "truffle run abigen"

View File

@ -0,0 +1,17 @@
const Wormhole = artifacts.require("Wormhole");
const MockBatchedVAASender = artifacts.require("MockBatchedVAASender");
module.exports = async function(callback) {
try {
const accounts = await web3.eth.getAccounts();
await MockBatchedVAASender.deploy();
const batchedSender = new web3.eth.Contract(MockBatchedVAASender.abi, MockBatchedVAASender.address);
await batchedSender.methods.setup(Wormhole.address).send({from: accounts[0]});
callback();
} catch (e) {
callback(e);
}
};

View File

@ -0,0 +1,29 @@
const MockBatchedVAASender = artifacts.require("MockBatchedVAASender");
module.exports = async function(callback) {
try {
const accounts = await web3.eth.getAccounts();
const batchedSender = await MockBatchedVAASender.deployed()
const contract = new web3.eth.Contract(MockBatchedVAASender.abi, batchedSender.address);
const nonce = Math.round(Date.now() / 1000);
const nonceHex = nonce.toString(16)
const res = await contract.methods.sendMultipleMessages(
"0x" + nonceHex,
"0x1",
32
).send({
value: 0,
from: accounts[0]
});
console.log('sendMultipleMessages response', res)
callback();
} catch (e) {
callback(e);
}
};

View File

@ -5,6 +5,7 @@ const path = require('path');
const Wormhole = artifacts.require("Wormhole");
const MockImplementation = artifacts.require("MockImplementation");
const Implementation = artifacts.require("Implementation");
const MockBatchedVAASender = artifacts.require("MockBatchedVAASender");
const testSigner1PK = "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";
const testSigner2PK = "892330666a850761e7370376430bb8c2aa1494072d3bfeaed0c4fa3d5a9135fe";
@ -114,6 +115,34 @@ contract("Wormhole", function () {
assert.equal(log.events.LogMessagePublished.returnValues.consistencyLevel, 32);
})
it("should log sequential sequence numbers for multi-VAA transactions", async function () {
const initialized = new web3.eth.Contract(ImplementationFullABI, Wormhole.address);
const accounts = await web3.eth.getAccounts();
const mockIntegration = new web3.eth.Contract(MockBatchedVAASender.abi, MockBatchedVAASender.address);
await mockIntegration.methods.sendMultipleMessages(
"0x1",
"0x1",
32
).send({
value: 0, // fees are set to 0 initially
from: accounts[0]
});
const events = (await initialized.getPastEvents('LogMessagePublished', {
fromBlock: 'latest'
}))
let firstSequence = Number(events[0].returnValues.sequence.toString())
let secondSequence = Number(events[1].returnValues.sequence.toString())
assert.equal(secondSequence, firstSequence + 1);
let thirdSequence = Number(events[2].returnValues.sequence.toString())
assert.equal(thirdSequence, secondSequence + 1);
})
it("should increase the sequence for an account", async function () {
const initialized = new web3.eth.Contract(ImplementationFullABI, Wormhole.address);
const accounts = await web3.eth.getAccounts();
@ -130,6 +159,33 @@ contract("Wormhole", function () {
assert.equal(log.events.LogMessagePublished.returnValues.sequence.toString(), "1");
})
it("should get the same nonce from all VAAs produced by a transaction", async function () {
const initialized = new web3.eth.Contract(ImplementationFullABI, Wormhole.address);
const accounts = await web3.eth.getAccounts();
const mockIntegration = new web3.eth.Contract(MockBatchedVAASender.abi, MockBatchedVAASender.address);
const nonce = Math.round(Date.now() / 1000);
const nonceHex = nonce.toString(16)
await mockIntegration.methods.sendMultipleMessages(
"0x" + nonceHex,
"0x1",
32
).send({
value: 0, // fees are set to 0 initially
from: accounts[0]
});
const events = (await initialized.getPastEvents('LogMessagePublished', {
fromBlock: 'latest'
}))
assert.equal(events[0].returnValues.nonce, nonce);
assert.equal(events[1].returnValues.nonce, nonce);
assert.equal(events[2].returnValues.nonce, nonce);
})
it("parses VMs correctly", async function () {
const initialized = new web3.eth.Contract(ImplementationFullABI, Wormhole.address);