evm: example send
This commit is contained in:
parent
92cfd72c2e
commit
602c793cd2
|
@ -0,0 +1,4 @@
|
|||
/build/
|
||||
/ethers-contracts/
|
||||
/lib/
|
||||
/node_modules/
|
|
@ -0,0 +1,114 @@
|
|||
// contracts/FastTransfer.sol
|
||||
// SPDX-License-Identifier: Apache 2
|
||||
|
||||
pragma solidity >=0.8.0 <0.9.0;
|
||||
|
||||
import "./libraries/external/BytesLib.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
interface IWormhole {
|
||||
function publishMessage(
|
||||
uint32 nonce,
|
||||
bytes memory payload,
|
||||
uint8 consistencyLevel
|
||||
) external payable returns (uint64 sequence);
|
||||
function messageFee() external view returns (uint256);
|
||||
}
|
||||
interface ITokenBridge {
|
||||
function wrapAndTransferETH(
|
||||
uint16 recipientChain,
|
||||
bytes32 recipient,
|
||||
uint256 arbiterFee,
|
||||
uint32 nonce
|
||||
) external payable returns (uint64 sequence);
|
||||
function chainId() external view returns (uint16);
|
||||
function WETH() external view returns (IWETH);
|
||||
}
|
||||
interface IWETH is IERC20 {
|
||||
function deposit() external payable;
|
||||
function withdraw(uint amount) external;
|
||||
}
|
||||
|
||||
// reuse Portal Transfer struct for convenience
|
||||
struct Transfer {
|
||||
// PayloadID uint8 = 1
|
||||
uint8 payloadID;
|
||||
// Amount being transferred (big-endian uint256)
|
||||
uint256 amount;
|
||||
// Address of the token. Left-zero-padded if shorter than 32 bytes
|
||||
bytes32 tokenAddress;
|
||||
// Chain ID of the token
|
||||
uint16 tokenChain;
|
||||
// Address of the recipient. Left-zero-padded if shorter than 32 bytes
|
||||
bytes32 to;
|
||||
// Chain ID of the recipient
|
||||
uint16 toChain;
|
||||
// Amount of tokens (big-endian uint256) that the user is willing to pay as relayer fee. Must be <= Amount.
|
||||
uint256 fee;
|
||||
}
|
||||
|
||||
contract FastTransfer {
|
||||
|
||||
IWormhole wormhole;
|
||||
ITokenBridge portal;
|
||||
|
||||
constructor(address wormholeAddress, address portalAddress) {
|
||||
wormhole = IWormhole(wormholeAddress);
|
||||
portal = ITokenBridge(portalAddress);
|
||||
}
|
||||
|
||||
function wrapAndTransferETH(
|
||||
uint16 recipientChain,
|
||||
bytes32 recipient,
|
||||
uint256 arbiterFee,
|
||||
uint32 nonce
|
||||
) public payable returns (uint64 fastSequence, uint64 portalSequence) {
|
||||
// Portal accounts for 1 fee, but we must account for 2
|
||||
uint wormholeFee = wormhole.messageFee();
|
||||
require(wormholeFee * 2 < msg.value, "value is smaller than wormhole fees");
|
||||
uint amount = msg.value - wormholeFee * 2;
|
||||
// Portal will normalize the amount to 8 decimals, so we should do the same
|
||||
uint normalizedAmount = normalizeAmount(amount, 18);
|
||||
Transfer memory fastTransfer = Transfer({
|
||||
payloadID: 1,
|
||||
amount: normalizedAmount,
|
||||
tokenAddress: bytes32(uint256(uint160(address(portal.WETH())))),
|
||||
tokenChain: portal.chainId(),
|
||||
to: recipient,
|
||||
toChain: recipientChain,
|
||||
fee: 0
|
||||
});
|
||||
fastSequence = wormhole.publishMessage{
|
||||
value : wormholeFee
|
||||
}(
|
||||
0,
|
||||
abi.encodePacked(
|
||||
fastTransfer.payloadID,
|
||||
fastTransfer.amount,
|
||||
fastTransfer.tokenAddress,
|
||||
fastTransfer.tokenChain,
|
||||
fastTransfer.to,
|
||||
fastTransfer.toChain,
|
||||
fastTransfer.fee
|
||||
),
|
||||
200
|
||||
);
|
||||
// Forward the remaining value sans the first fee
|
||||
portalSequence = portal.wrapAndTransferETH{
|
||||
value: msg.value - wormholeFee
|
||||
}(
|
||||
recipientChain,
|
||||
recipient, // TODO: receiving chain pool
|
||||
arbiterFee,
|
||||
nonce
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeAmount(uint256 amount, uint8 decimals) internal pure returns(uint256){
|
||||
if (decimals > 8) {
|
||||
amount /= 10 ** (decimals - 8);
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,510 @@
|
|||
// SPDX-License-Identifier: Unlicense
|
||||
/*
|
||||
* @title Solidity Bytes Arrays Utils
|
||||
* @author Gonçalo Sá <goncalo.sa@consensys.net>
|
||||
*
|
||||
* @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
|
||||
* The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
|
||||
*/
|
||||
pragma solidity >=0.8.0 <0.9.0;
|
||||
|
||||
|
||||
library BytesLib {
|
||||
function concat(
|
||||
bytes memory _preBytes,
|
||||
bytes memory _postBytes
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
bytes memory tempBytes;
|
||||
|
||||
assembly {
|
||||
// Get a location of some free memory and store it in tempBytes as
|
||||
// Solidity does for memory variables.
|
||||
tempBytes := mload(0x40)
|
||||
|
||||
// Store the length of the first bytes array at the beginning of
|
||||
// the memory for tempBytes.
|
||||
let length := mload(_preBytes)
|
||||
mstore(tempBytes, length)
|
||||
|
||||
// Maintain a memory counter for the current write location in the
|
||||
// temp bytes array by adding the 32 bytes for the array length to
|
||||
// the starting location.
|
||||
let mc := add(tempBytes, 0x20)
|
||||
// Stop copying when the memory counter reaches the length of the
|
||||
// first bytes array.
|
||||
let end := add(mc, length)
|
||||
|
||||
for {
|
||||
// Initialize a copy counter to the start of the _preBytes data,
|
||||
// 32 bytes into its memory.
|
||||
let cc := add(_preBytes, 0x20)
|
||||
} lt(mc, end) {
|
||||
// Increase both counters by 32 bytes each iteration.
|
||||
mc := add(mc, 0x20)
|
||||
cc := add(cc, 0x20)
|
||||
} {
|
||||
// Write the _preBytes data into the tempBytes memory 32 bytes
|
||||
// at a time.
|
||||
mstore(mc, mload(cc))
|
||||
}
|
||||
|
||||
// Add the length of _postBytes to the current length of tempBytes
|
||||
// and store it as the new length in the first 32 bytes of the
|
||||
// tempBytes memory.
|
||||
length := mload(_postBytes)
|
||||
mstore(tempBytes, add(length, mload(tempBytes)))
|
||||
|
||||
// Move the memory counter back from a multiple of 0x20 to the
|
||||
// actual end of the _preBytes data.
|
||||
mc := end
|
||||
// Stop copying when the memory counter reaches the new combined
|
||||
// length of the arrays.
|
||||
end := add(mc, length)
|
||||
|
||||
for {
|
||||
let cc := add(_postBytes, 0x20)
|
||||
} lt(mc, end) {
|
||||
mc := add(mc, 0x20)
|
||||
cc := add(cc, 0x20)
|
||||
} {
|
||||
mstore(mc, mload(cc))
|
||||
}
|
||||
|
||||
// Update the free-memory pointer by padding our last write location
|
||||
// to 32 bytes: add 31 bytes to the end of tempBytes to move to the
|
||||
// next 32 byte block, then round down to the nearest multiple of
|
||||
// 32. If the sum of the length of the two arrays is zero then add
|
||||
// one before rounding down to leave a blank 32 bytes (the length block with 0).
|
||||
mstore(0x40, and(
|
||||
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
|
||||
not(31) // Round down to the nearest 32 bytes.
|
||||
))
|
||||
}
|
||||
|
||||
return tempBytes;
|
||||
}
|
||||
|
||||
function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
|
||||
assembly {
|
||||
// Read the first 32 bytes of _preBytes storage, which is the length
|
||||
// of the array. (We don't need to use the offset into the slot
|
||||
// because arrays use the entire slot.)
|
||||
let fslot := sload(_preBytes.slot)
|
||||
// Arrays of 31 bytes or less have an even value in their slot,
|
||||
// while longer arrays have an odd value. The actual length is
|
||||
// the slot divided by two for odd values, and the lowest order
|
||||
// byte divided by two for even values.
|
||||
// If the slot is even, bitwise and the slot with 255 and divide by
|
||||
// two to get the length. If the slot is odd, bitwise and the slot
|
||||
// with -1 and divide by two.
|
||||
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
|
||||
let mlength := mload(_postBytes)
|
||||
let newlength := add(slength, mlength)
|
||||
// slength can contain both the length and contents of the array
|
||||
// if length < 32 bytes so let's prepare for that
|
||||
// v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
|
||||
switch add(lt(slength, 32), lt(newlength, 32))
|
||||
case 2 {
|
||||
// Since the new array still fits in the slot, we just need to
|
||||
// update the contents of the slot.
|
||||
// uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
|
||||
sstore(
|
||||
_preBytes.slot,
|
||||
// all the modifications to the slot are inside this
|
||||
// next block
|
||||
add(
|
||||
// we can just add to the slot contents because the
|
||||
// bytes we want to change are the LSBs
|
||||
fslot,
|
||||
add(
|
||||
mul(
|
||||
div(
|
||||
// load the bytes from memory
|
||||
mload(add(_postBytes, 0x20)),
|
||||
// zero all bytes to the right
|
||||
exp(0x100, sub(32, mlength))
|
||||
),
|
||||
// and now shift left the number of bytes to
|
||||
// leave space for the length in the slot
|
||||
exp(0x100, sub(32, newlength))
|
||||
),
|
||||
// increase length by the double of the memory
|
||||
// bytes length
|
||||
mul(mlength, 2)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
case 1 {
|
||||
// The stored value fits in the slot, but the combined value
|
||||
// will exceed it.
|
||||
// get the keccak hash to get the contents of the array
|
||||
mstore(0x0, _preBytes.slot)
|
||||
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
|
||||
|
||||
// save new length
|
||||
sstore(_preBytes.slot, add(mul(newlength, 2), 1))
|
||||
|
||||
// The contents of the _postBytes array start 32 bytes into
|
||||
// the structure. Our first read should obtain the `submod`
|
||||
// bytes that can fit into the unused space in the last word
|
||||
// of the stored array. To get this, we read 32 bytes starting
|
||||
// from `submod`, so the data we read overlaps with the array
|
||||
// contents by `submod` bytes. Masking the lowest-order
|
||||
// `submod` bytes allows us to add that value directly to the
|
||||
// stored value.
|
||||
|
||||
let submod := sub(32, slength)
|
||||
let mc := add(_postBytes, submod)
|
||||
let end := add(_postBytes, mlength)
|
||||
let mask := sub(exp(0x100, submod), 1)
|
||||
|
||||
sstore(
|
||||
sc,
|
||||
add(
|
||||
and(
|
||||
fslot,
|
||||
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
|
||||
),
|
||||
and(mload(mc), mask)
|
||||
)
|
||||
)
|
||||
|
||||
for {
|
||||
mc := add(mc, 0x20)
|
||||
sc := add(sc, 1)
|
||||
} lt(mc, end) {
|
||||
sc := add(sc, 1)
|
||||
mc := add(mc, 0x20)
|
||||
} {
|
||||
sstore(sc, mload(mc))
|
||||
}
|
||||
|
||||
mask := exp(0x100, sub(mc, end))
|
||||
|
||||
sstore(sc, mul(div(mload(mc), mask), mask))
|
||||
}
|
||||
default {
|
||||
// get the keccak hash to get the contents of the array
|
||||
mstore(0x0, _preBytes.slot)
|
||||
// Start copying to the last used word of the stored array.
|
||||
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
|
||||
|
||||
// save new length
|
||||
sstore(_preBytes.slot, add(mul(newlength, 2), 1))
|
||||
|
||||
// Copy over the first `submod` bytes of the new data as in
|
||||
// case 1 above.
|
||||
let slengthmod := mod(slength, 32)
|
||||
let mlengthmod := mod(mlength, 32)
|
||||
let submod := sub(32, slengthmod)
|
||||
let mc := add(_postBytes, submod)
|
||||
let end := add(_postBytes, mlength)
|
||||
let mask := sub(exp(0x100, submod), 1)
|
||||
|
||||
sstore(sc, add(sload(sc), and(mload(mc), mask)))
|
||||
|
||||
for {
|
||||
sc := add(sc, 1)
|
||||
mc := add(mc, 0x20)
|
||||
} lt(mc, end) {
|
||||
sc := add(sc, 1)
|
||||
mc := add(mc, 0x20)
|
||||
} {
|
||||
sstore(sc, mload(mc))
|
||||
}
|
||||
|
||||
mask := exp(0x100, sub(mc, end))
|
||||
|
||||
sstore(sc, mul(div(mload(mc), mask), mask))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function slice(
|
||||
bytes memory _bytes,
|
||||
uint256 _start,
|
||||
uint256 _length
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
require(_length + 31 >= _length, "slice_overflow");
|
||||
require(_bytes.length >= _start + _length, "slice_outOfBounds");
|
||||
|
||||
bytes memory tempBytes;
|
||||
|
||||
assembly {
|
||||
switch iszero(_length)
|
||||
case 0 {
|
||||
// Get a location of some free memory and store it in tempBytes as
|
||||
// Solidity does for memory variables.
|
||||
tempBytes := mload(0x40)
|
||||
|
||||
// The first word of the slice result is potentially a partial
|
||||
// word read from the original array. To read it, we calculate
|
||||
// the length of that partial word and start copying that many
|
||||
// bytes into the array. The first word we copy will start with
|
||||
// data we don't care about, but the last `lengthmod` bytes will
|
||||
// land at the beginning of the contents of the new array. When
|
||||
// we're done copying, we overwrite the full first word with
|
||||
// the actual length of the slice.
|
||||
let lengthmod := and(_length, 31)
|
||||
|
||||
// The multiplication in the next line is necessary
|
||||
// because when slicing multiples of 32 bytes (lengthmod == 0)
|
||||
// the following copy loop was copying the origin's length
|
||||
// and then ending prematurely not copying everything it should.
|
||||
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
|
||||
let end := add(mc, _length)
|
||||
|
||||
for {
|
||||
// The multiplication in the next line has the same exact purpose
|
||||
// as the one above.
|
||||
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
|
||||
} lt(mc, end) {
|
||||
mc := add(mc, 0x20)
|
||||
cc := add(cc, 0x20)
|
||||
} {
|
||||
mstore(mc, mload(cc))
|
||||
}
|
||||
|
||||
mstore(tempBytes, _length)
|
||||
|
||||
//update free-memory pointer
|
||||
//allocating the array padded to 32 bytes like the compiler does now
|
||||
mstore(0x40, and(add(mc, 31), not(31)))
|
||||
}
|
||||
//if we want a zero-length slice let's just return a zero-length array
|
||||
default {
|
||||
tempBytes := mload(0x40)
|
||||
//zero out the 32 bytes slice we are about to return
|
||||
//we need to do it because Solidity does not garbage collect
|
||||
mstore(tempBytes, 0)
|
||||
|
||||
mstore(0x40, add(tempBytes, 0x20))
|
||||
}
|
||||
}
|
||||
|
||||
return tempBytes;
|
||||
}
|
||||
|
||||
function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
|
||||
require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
|
||||
address tempAddress;
|
||||
|
||||
assembly {
|
||||
tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
|
||||
}
|
||||
|
||||
return tempAddress;
|
||||
}
|
||||
|
||||
function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
|
||||
require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
|
||||
uint8 tempUint;
|
||||
|
||||
assembly {
|
||||
tempUint := mload(add(add(_bytes, 0x1), _start))
|
||||
}
|
||||
|
||||
return tempUint;
|
||||
}
|
||||
|
||||
function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
|
||||
require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
|
||||
uint16 tempUint;
|
||||
|
||||
assembly {
|
||||
tempUint := mload(add(add(_bytes, 0x2), _start))
|
||||
}
|
||||
|
||||
return tempUint;
|
||||
}
|
||||
|
||||
function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
|
||||
require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
|
||||
uint32 tempUint;
|
||||
|
||||
assembly {
|
||||
tempUint := mload(add(add(_bytes, 0x4), _start))
|
||||
}
|
||||
|
||||
return tempUint;
|
||||
}
|
||||
|
||||
function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
|
||||
require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
|
||||
uint64 tempUint;
|
||||
|
||||
assembly {
|
||||
tempUint := mload(add(add(_bytes, 0x8), _start))
|
||||
}
|
||||
|
||||
return tempUint;
|
||||
}
|
||||
|
||||
function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
|
||||
require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
|
||||
uint96 tempUint;
|
||||
|
||||
assembly {
|
||||
tempUint := mload(add(add(_bytes, 0xc), _start))
|
||||
}
|
||||
|
||||
return tempUint;
|
||||
}
|
||||
|
||||
function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
|
||||
require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
|
||||
uint128 tempUint;
|
||||
|
||||
assembly {
|
||||
tempUint := mload(add(add(_bytes, 0x10), _start))
|
||||
}
|
||||
|
||||
return tempUint;
|
||||
}
|
||||
|
||||
function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
|
||||
require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
|
||||
uint256 tempUint;
|
||||
|
||||
assembly {
|
||||
tempUint := mload(add(add(_bytes, 0x20), _start))
|
||||
}
|
||||
|
||||
return tempUint;
|
||||
}
|
||||
|
||||
function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
|
||||
require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
|
||||
bytes32 tempBytes32;
|
||||
|
||||
assembly {
|
||||
tempBytes32 := mload(add(add(_bytes, 0x20), _start))
|
||||
}
|
||||
|
||||
return tempBytes32;
|
||||
}
|
||||
|
||||
function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
|
||||
bool success = true;
|
||||
|
||||
assembly {
|
||||
let length := mload(_preBytes)
|
||||
|
||||
// if lengths don't match the arrays are not equal
|
||||
switch eq(length, mload(_postBytes))
|
||||
case 1 {
|
||||
// cb is a circuit breaker in the for loop since there's
|
||||
// no said feature for inline assembly loops
|
||||
// cb = 1 - don't breaker
|
||||
// cb = 0 - break
|
||||
let cb := 1
|
||||
|
||||
let mc := add(_preBytes, 0x20)
|
||||
let end := add(mc, length)
|
||||
|
||||
for {
|
||||
let cc := add(_postBytes, 0x20)
|
||||
// the next line is the loop condition:
|
||||
// while(uint256(mc < end) + cb == 2)
|
||||
} eq(add(lt(mc, end), cb), 2) {
|
||||
mc := add(mc, 0x20)
|
||||
cc := add(cc, 0x20)
|
||||
} {
|
||||
// if any of these checks fails then arrays are not equal
|
||||
if iszero(eq(mload(mc), mload(cc))) {
|
||||
// unsuccess:
|
||||
success := 0
|
||||
cb := 0
|
||||
}
|
||||
}
|
||||
}
|
||||
default {
|
||||
// unsuccess:
|
||||
success := 0
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
function equalStorage(
|
||||
bytes storage _preBytes,
|
||||
bytes memory _postBytes
|
||||
)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
assembly {
|
||||
// we know _preBytes_offset is 0
|
||||
let fslot := sload(_preBytes.slot)
|
||||
// Decode the length of the stored array like in concatStorage().
|
||||
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
|
||||
let mlength := mload(_postBytes)
|
||||
|
||||
// if lengths don't match the arrays are not equal
|
||||
switch eq(slength, mlength)
|
||||
case 1 {
|
||||
// slength can contain both the length and contents of the array
|
||||
// if length < 32 bytes so let's prepare for that
|
||||
// v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
|
||||
if iszero(iszero(slength)) {
|
||||
switch lt(slength, 32)
|
||||
case 1 {
|
||||
// blank the last byte which is the length
|
||||
fslot := mul(div(fslot, 0x100), 0x100)
|
||||
|
||||
if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
|
||||
// unsuccess:
|
||||
success := 0
|
||||
}
|
||||
}
|
||||
default {
|
||||
// cb is a circuit breaker in the for loop since there's
|
||||
// no said feature for inline assembly loops
|
||||
// cb = 1 - don't breaker
|
||||
// cb = 0 - break
|
||||
let cb := 1
|
||||
|
||||
// get the keccak hash to get the contents of the array
|
||||
mstore(0x0, _preBytes.slot)
|
||||
let sc := keccak256(0x0, 0x20)
|
||||
|
||||
let mc := add(_postBytes, 0x20)
|
||||
let end := add(mc, mlength)
|
||||
|
||||
// the next line is the loop condition:
|
||||
// while(uint256(mc < end) + cb == 2)
|
||||
for {} eq(add(lt(mc, end), cb), 2) {
|
||||
sc := add(sc, 1)
|
||||
mc := add(mc, 0x20)
|
||||
} {
|
||||
if iszero(eq(sload(sc), mload(mc))) {
|
||||
// unsuccess:
|
||||
success := 0
|
||||
cb := 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default {
|
||||
// unsuccess:
|
||||
success := 0
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "example-portal-fast-withdrawal-evm",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "npm run generate && tsc && jest --config jestconfig.json --verbose",
|
||||
"genTypes": "typechain --target ethers-v5 --out-dir ethers-contracts/abi --show-stack-traces ./build/contracts/*.json",
|
||||
"generate": "rimraf lib && rimraf ethers-contracts && rimraf build && truffle compile && npm run genTypes",
|
||||
"build": "truffle compile",
|
||||
"truffle": "truffle"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
||||
"@openzeppelin/contracts": "^4.3.1",
|
||||
"@typechain/ethers-v5": "^7.0.1",
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/long": "^4.0.1",
|
||||
"@types/node": "^16.6.1",
|
||||
"@types/react": "^17.0.19",
|
||||
"copy-dir": "^1.3.0",
|
||||
"esm": "^3.2.25",
|
||||
"ethers": "5.4.4",
|
||||
"jest": "^27.3.1",
|
||||
"prettier": "^2.3.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"truffle": "^5.3.14",
|
||||
"ts-jest": "^27.0.7",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-prettier": "^1.18.0",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certusone/wormhole-sdk": "^0.6.5",
|
||||
"@chainsafe/truffle-plugin-abigen": "^0.0.1",
|
||||
"@truffle/hdwallet-provider": "^1.7.0",
|
||||
"truffle-plugin-verify": "^0.5.11"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
const HDWalletProvider = require("@truffle/hdwallet-provider");
|
||||
|
||||
module.exports = {
|
||||
networks: {
|
||||
development: {
|
||||
host: "127.0.0.1",
|
||||
port: 8545,
|
||||
network_id: "*",
|
||||
},
|
||||
ethereum_testnet: {
|
||||
provider: () => {
|
||||
return new HDWalletProvider(
|
||||
process.env.MNEMONIC,
|
||||
"https://rpc.ankr.com/eth_goerli"
|
||||
);
|
||||
},
|
||||
network_id: "5",
|
||||
},
|
||||
},
|
||||
mocha: {
|
||||
// timeout: 100000
|
||||
},
|
||||
// Configure your compilers
|
||||
compilers: {
|
||||
solc: {
|
||||
version: "0.8.4",
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: ["@chainsafe/truffle-plugin-abigen", "truffle-plugin-verify"],
|
||||
};
|
Loading…
Reference in New Issue