commit
e25ae87947
|
@ -4,58 +4,13 @@ on:
|
|||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- dev.v2
|
||||
- main
|
||||
jobs:
|
||||
# Run the full Tilt build and wait for it to converge
|
||||
tilt:
|
||||
runs-on: tilt-kube-public
|
||||
|
||||
# Cancel previous builds on the same branch/ref. Full runs are expensive
|
||||
# and capacity is limited, so we want to avoid running multiple builds
|
||||
# in parallel even if it means skipping CI runs on permanent branches
|
||||
# (unfortunately, we can't differentiate between temporary and permanent
|
||||
# refs without duplicating the entire logic).
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Expand for link to Tilt dashboard (only available during build)
|
||||
run: >
|
||||
echo "Tilt progress dashboard: https://$DASHBOARD_URL"
|
||||
- run: |
|
||||
kubectl config set-context ci --namespace=$DEPLOY_NS
|
||||
kubectl config use-context ci
|
||||
|
||||
- run: tilt ci -- --ci --namespace=$DEPLOY_NS --num=1
|
||||
timeout-minutes: 60
|
||||
|
||||
# Clean up k8s resources
|
||||
- run: kubectl delete --namespace=$DEPLOY_NS service,statefulset,configmap,pod,job --all
|
||||
if: always()
|
||||
|
||||
# Verify whether the Makefile builds the node (no dependencies other than Go)
|
||||
node:
|
||||
ethereum:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
go-version: '1.17.5'
|
||||
- run: make node
|
||||
|
||||
# Run linters, Go tests and other outside-of-Tilt things.
|
||||
lint-and-tests:
|
||||
# The linter is slow enough that we want to run it on the self-hosted runner
|
||||
runs-on: tilt-kube-public
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17.5'
|
||||
- run: make generate && ./lint.sh
|
||||
- run: cd node && go test -v ./...
|
||||
node-version: "16"
|
||||
- run: cd ethereum && make build && make test
|
||||
|
|
2
Makefile
2
Makefile
|
@ -33,7 +33,7 @@ sdk/js/src/icco/__tests__/tilt.json:
|
|||
## Deploy Contracts to Tilt
|
||||
tilt-deploy: ethereum terra
|
||||
@if ! pgrep tilt; then echo "Error: tilt not running. Start it before running tests"; exit 1; fi
|
||||
cd ethereum && make tilt-deploy
|
||||
cd ethereum && make tilt-deploy && npx truffle exec scripts/register_tilt_contributors.js --network eth_devnet
|
||||
# cd terra && make terrad-deploy
|
||||
# cd ethereum && node scripts/
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
wormhole
|
||||
ganache.log
|
|
@ -19,7 +19,7 @@ build: node_modules ${SOURCE_FILES}
|
|||
cp $< $@
|
||||
|
||||
wormhole/ethereum/build:
|
||||
git clone --depth 1 --branch dev.v2 --single-branch git@github.com:certusone/wormhole.git
|
||||
git clone --depth 1 --branch dev.v2 --single-branch https://github.com/certusone/wormhole.git
|
||||
cd wormhole/ethereum && npm ci && npm run build && make .env
|
||||
|
||||
.PHONY: test
|
||||
|
@ -30,7 +30,8 @@ test: .env build wormhole/ethereum/build
|
|||
sleep 5
|
||||
cd wormhole/ethereum && npm run migrate
|
||||
npm test || (pkill -f ganache-cli && exit 1)
|
||||
pkill -f ganache-cli || true
|
||||
pkill -f ganache-cli
|
||||
exit 0
|
||||
|
||||
.PHONY: tilt-deploy
|
||||
tilt-deploy: .env build
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// contracts/Structs.sol
|
||||
// SPDX-License-Identifier: Apache 2
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
|
||||
|
||||
contract BridgeToken is BeaconProxy {
|
||||
constructor(address beacon, bytes memory data) BeaconProxy(beacon, data) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
// contracts/TokenImplementation.sol
|
||||
// SPDX-License-Identifier: Apache 2
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "./TokenState.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/utils/Context.sol";
|
||||
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
|
||||
|
||||
// Based on the OpenZepplin ERC20 implementation, licensed under MIT
|
||||
contract TokenImplementation is TokenState, Context {
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
function initialize(
|
||||
string memory name_,
|
||||
string memory symbol_,
|
||||
uint8 decimals_,
|
||||
uint64 sequence_,
|
||||
|
||||
address owner_,
|
||||
|
||||
uint16 chainId_,
|
||||
bytes32 nativeContract_
|
||||
) initializer public {
|
||||
_state.name = name_;
|
||||
_state.symbol = symbol_;
|
||||
_state.decimals = decimals_;
|
||||
_state.metaLastUpdatedSequence = sequence_;
|
||||
|
||||
_state.owner = owner_;
|
||||
|
||||
_state.chainId = chainId_;
|
||||
_state.nativeContract = nativeContract_;
|
||||
}
|
||||
|
||||
function name() public view returns (string memory) {
|
||||
return string(abi.encodePacked(_state.name, " (Wormhole)"));
|
||||
}
|
||||
|
||||
function symbol() public view returns (string memory) {
|
||||
return _state.symbol;
|
||||
}
|
||||
|
||||
function owner() public view returns (address) {
|
||||
return _state.owner;
|
||||
}
|
||||
|
||||
function decimals() public view returns (uint8) {
|
||||
return _state.decimals;
|
||||
}
|
||||
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return _state.totalSupply;
|
||||
}
|
||||
|
||||
function chainId() public view returns (uint16) {
|
||||
return _state.chainId;
|
||||
}
|
||||
|
||||
function nativeContract() public view returns (bytes32) {
|
||||
return _state.nativeContract;
|
||||
}
|
||||
|
||||
function balanceOf(address account_) public view returns (uint256) {
|
||||
return _state.balances[account_];
|
||||
}
|
||||
|
||||
function transfer(address recipient_, uint256 amount_) public returns (bool) {
|
||||
_transfer(_msgSender(), recipient_, amount_);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address owner_, address spender_) public view returns (uint256) {
|
||||
return _state.allowances[owner_][spender_];
|
||||
}
|
||||
|
||||
function approve(address spender_, uint256 amount_) public returns (bool) {
|
||||
_approve(_msgSender(), spender_, amount_);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(address sender_, address recipient_, uint256 amount_) public returns (bool) {
|
||||
_transfer(sender_, recipient_, amount_);
|
||||
|
||||
uint256 currentAllowance = _state.allowances[sender_][_msgSender()];
|
||||
require(currentAllowance >= amount_, "ERC20: transfer amount exceeds allowance");
|
||||
_approve(sender_, _msgSender(), currentAllowance - amount_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function increaseAllowance(address spender_, uint256 addedValue_) public returns (bool) {
|
||||
_approve(_msgSender(), spender_, _state.allowances[_msgSender()][spender_] + addedValue_);
|
||||
return true;
|
||||
}
|
||||
|
||||
function decreaseAllowance(address spender_, uint256 subtractedValue_) public returns (bool) {
|
||||
uint256 currentAllowance = _state.allowances[_msgSender()][spender_];
|
||||
require(currentAllowance >= subtractedValue_, "ERC20: decreased allowance below zero");
|
||||
_approve(_msgSender(), spender_, currentAllowance - subtractedValue_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function _transfer(address sender_, address recipient_, uint256 amount_) internal {
|
||||
require(sender_ != address(0), "ERC20: transfer from the zero address");
|
||||
require(recipient_ != address(0), "ERC20: transfer to the zero address");
|
||||
|
||||
uint256 senderBalance = _state.balances[sender_];
|
||||
require(senderBalance >= amount_, "ERC20: transfer amount exceeds balance");
|
||||
_state.balances[sender_] = senderBalance - amount_;
|
||||
_state.balances[recipient_] += amount_;
|
||||
|
||||
emit Transfer(sender_, recipient_, amount_);
|
||||
}
|
||||
|
||||
function mint(address account_, uint256 amount_) public onlyOwner {
|
||||
_mint(account_, amount_);
|
||||
}
|
||||
|
||||
function _mint(address account_, uint256 amount_) internal {
|
||||
require(account_ != address(0), "ERC20: mint to the zero address");
|
||||
|
||||
_state.totalSupply += amount_;
|
||||
_state.balances[account_] += amount_;
|
||||
emit Transfer(address(0), account_, amount_);
|
||||
}
|
||||
|
||||
function burn(address account_, uint256 amount_) public onlyOwner {
|
||||
_burn(account_, amount_);
|
||||
}
|
||||
|
||||
function _burn(address account_, uint256 amount_) internal {
|
||||
require(account_ != address(0), "ERC20: burn from the zero address");
|
||||
|
||||
uint256 accountBalance = _state.balances[account_];
|
||||
require(accountBalance >= amount_, "ERC20: burn amount exceeds balance");
|
||||
_state.balances[account_] = accountBalance - amount_;
|
||||
_state.totalSupply -= amount_;
|
||||
|
||||
emit Transfer(account_, address(0), amount_);
|
||||
}
|
||||
|
||||
function _approve(address owner_, address spender_, uint256 amount_) internal virtual {
|
||||
require(owner_ != address(0), "ERC20: approve from the zero address");
|
||||
require(spender_ != address(0), "ERC20: approve to the zero address");
|
||||
|
||||
_state.allowances[owner_][spender_] = amount_;
|
||||
emit Approval(owner_, spender_, amount_);
|
||||
}
|
||||
|
||||
function updateDetails(string memory name_, string memory symbol_, uint64 sequence_) public onlyOwner {
|
||||
require(_state.metaLastUpdatedSequence < sequence_, "current metadata is up to date");
|
||||
|
||||
_state.name = name_;
|
||||
_state.symbol = symbol_;
|
||||
_state.metaLastUpdatedSequence = sequence_;
|
||||
}
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(owner() == _msgSender(), "caller is not the owner");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier initializer() {
|
||||
require(
|
||||
!_state.initialized,
|
||||
"Already initialized"
|
||||
);
|
||||
|
||||
_state.initialized = true;
|
||||
|
||||
_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// contracts/State.sol
|
||||
// SPDX-License-Identifier: Apache 2
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
contract TokenStorage {
|
||||
struct State {
|
||||
string name;
|
||||
string symbol;
|
||||
|
||||
uint64 metaLastUpdatedSequence;
|
||||
|
||||
uint256 totalSupply;
|
||||
uint8 decimals;
|
||||
|
||||
mapping(address => uint256) balances;
|
||||
|
||||
mapping(address => mapping(address => uint256)) allowances;
|
||||
|
||||
address owner;
|
||||
|
||||
bool initialized;
|
||||
|
||||
uint16 chainId;
|
||||
bytes32 nativeContract;
|
||||
}
|
||||
}
|
||||
|
||||
contract TokenState {
|
||||
TokenStorage.State _state;
|
||||
}
|
|
@ -5,25 +5,30 @@ const elliptic = require("elliptic");
|
|||
const TokenSaleConductor = artifacts.require("TokenSaleConductor");
|
||||
const TokenSaleContributor = artifacts.require("TokenSaleContributor");
|
||||
|
||||
//sdk.setDefaultWasm("node");
|
||||
|
||||
const ConductorImplementationFullABI = jsonfile.readFileSync(
|
||||
"../build/contracts/ConductorImplementation.json"
|
||||
).abi;
|
||||
|
||||
const fs = require("fs");
|
||||
|
||||
const tilt = JSON.parse(
|
||||
fs.readFileSync(`${__dirname}/../../tilt.json`, "utf8")
|
||||
);
|
||||
|
||||
module.exports = async function(callback) {
|
||||
try {
|
||||
const emitters = new Map();
|
||||
{
|
||||
// TODO: grab this from the tilt.json file...
|
||||
// const solanaProgAddr = "22mamxmojFWBdbGqaxTH46HBAgAY2bJRiGJJHfNRNQ95"; //TBD Not used, because I could not get WH sdk to be available in tilt.
|
||||
const solanaEmitterAddr =
|
||||
"0xaeab35a8d36bbaad38154ca4ca6a0770e7009326316d59ef2c8a2123e90d174c"; // Derived from solanaProgAddr using await sdk.getEmitterAddressSolana(..);
|
||||
|
||||
// Build chainId -> ContributorAddr map.
|
||||
const ethEmitterAddress =
|
||||
"0x000000000000000000000000" + TokenSaleContributor.address.substr(2);
|
||||
"0x000000000000000000000000" + tilt.ethContributorAddress.substring(2);
|
||||
const bscEmitterAddress =
|
||||
"0x000000000000000000000000" + TokenSaleContributor.address.substr(2);
|
||||
"0x000000000000000000000000" + tilt.bscContributorAddress.substring(2);
|
||||
emitters.set(1, solanaEmitterAddr);
|
||||
emitters.set(2, ethEmitterAddress);
|
||||
emitters.set(4, bscEmitterAddress);
|
||||
|
@ -50,4 +55,4 @@ module.exports = async function(callback) {
|
|||
} catch (e) {
|
||||
callback(e);
|
||||
}
|
||||
};
|
||||
};
|
|
@ -11,7 +11,7 @@
|
|||
"repository": "https://github.com/certusone/wormhole-icco/tree/main/sdk/js",
|
||||
"scripts": {
|
||||
"build-contracts": "npm run build --prefix ../../ethereum && node scripts/copyContracts.js && typechain --target=ethers-v5 --out-dir=src/ethers-contracts contracts/*.json",
|
||||
"build-abis": "typechain --target=ethers-v5 --out-dir=src/ethers-contracts/abi src/abi/Wormhole.abi.json",
|
||||
"build-abis": "typechain --target=ethers-v5 --out-dir=src/ethers-contracts/abi",
|
||||
"build-deps": "npm run build-abis && npm run build-contracts",
|
||||
"build-lib": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && node scripts/copyEthersTypes.js",
|
||||
"build-all": "npm run build-deps && npm run build-lib",
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import { ethers } from "ethers";
|
||||
import { ChainId } from "@certusone/wormhole-sdk";
|
||||
|
||||
import { Conductor__factory } from "../ethers-contracts";
|
||||
|
||||
export async function registerChainOnEth(
|
||||
conductorAddress: string,
|
||||
signedVaa: Uint8Array,
|
||||
contributorChain: ChainId,
|
||||
contributorAddress: Uint8Array,
|
||||
wallet: ethers.Wallet
|
||||
): Promise<ethers.ContractReceipt> {
|
||||
const contributor = Conductor__factory.connect(conductorAddress, wallet);
|
||||
const tx = await contributor.registerChain(signedVaa);
|
||||
const tx = await contributor.registerChain(
|
||||
contributorChain,
|
||||
contributorAddress
|
||||
);
|
||||
return tx.wait();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue