diff --git a/README.md b/README.md index ce68a42..fe91729 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,20 @@ In a world where Ethereum finality takes ~18 minutes and Wormhole offers instant, un-finalized messaging in addition to finalized messaging, this repo imagines a Portal which can offer even faster transfers. _Gotta go fast!_ + +## Concept + +Provide liquidity for fast withdrawals in exchange for fee emissions (at the risk of never receiving the Portal transfer due to rollbacks). If pooled funds exist on the target chain, the user can complete their transfer immediately. If not, they can complete their transfer after their portal funds arrive. + +## Progress + +- [x] Send fast transfer and portal transfer +- [ ] Redeem fast transfer to user, 1% to pool +- [ ] Redeem portal transfer to pool +- [ ] Setup pool via creating and registering of LP token +- [ ] Portal ABI parity +- [ ] Ownable and owner-only registration + +## Disclaimer + +This is an example only, not suitable for practically anything! diff --git a/evm/.gitignore b/evm/.gitignore index a814815..db41883 100644 --- a/evm/.gitignore +++ b/evm/.gitignore @@ -2,3 +2,4 @@ /ethers-contracts/ /lib/ /node_modules/ +addresses.json diff --git a/evm/package.json b/evm/package.json index 4a721c6..e9ada8f 100644 --- a/evm/package.json +++ b/evm/package.json @@ -5,7 +5,10 @@ "main": "index.js", "scripts": { "build": "truffle compile", - "deploy-devnet": "truffle compile && truffle exec scripts/deploy_devnet.js --network development" + "deploy-devnet": "truffle compile && truffle exec scripts/deploy_devnet.js --network development", + "test-devnet": "node scripts/test_devnet.js", + "deploy-testnet": "truffle compile && truffle exec scripts/deploy_testnet.js --network ethereum_testnet", + "test-testnet": "node scripts/test_testnet.js" }, "author": "", "license": "ISC", diff --git a/evm/scripts/deploy_devnet.js b/evm/scripts/deploy_devnet.js index e9ec224..a2bf708 100644 --- a/evm/scripts/deploy_devnet.js +++ b/evm/scripts/deploy_devnet.js @@ -1,9 +1,20 @@ const FastTransfer = artifacts.require("FastTransfer"); +let addresses = {}; +try { + addresses = require("../addresses.json"); +} catch (e) {} +const { CONTRACTS } = require("@certusone/wormhole-sdk"); +const fs = require("fs"); module.exports = async function (callback) { try { - const ft = await FastTransfer.new(); + const ft = await FastTransfer.new( + CONTRACTS.DEVNET.ethereum.core, + CONTRACTS.DEVNET.ethereum.token_bridge + ); console.log("tx: " + ft.transactionHash); console.log("FastTransfer address: " + ft.address); + addresses.devnet = ft.address; + fs.writeFileSync("./addresses.json", JSON.stringify(addresses)); callback(); } catch (e) { callback(e); diff --git a/evm/scripts/deploy_testnet.js b/evm/scripts/deploy_testnet.js new file mode 100644 index 0000000..40b083b --- /dev/null +++ b/evm/scripts/deploy_testnet.js @@ -0,0 +1,22 @@ +const FastTransfer = artifacts.require("FastTransfer"); +let addresses = {}; +try { + addresses = require("../addresses.json"); +} catch (e) {} +const { CONTRACTS } = require("@certusone/wormhole-sdk"); +const fs = require("fs"); +module.exports = async function (callback) { + try { + const ft = await FastTransfer.new( + CONTRACTS.TESTNET.ethereum.core, + CONTRACTS.TESTNET.ethereum.token_bridge + ); + console.log("tx: " + ft.transactionHash); + console.log("FastTransfer address: " + ft.address); + addresses.testnet = ft.address; + fs.writeFileSync("./addresses.json", JSON.stringify(addresses)); + callback(); + } catch (e) { + callback(e); + } +}; diff --git a/evm/scripts/test_devnet.js b/evm/scripts/test_devnet.js new file mode 100644 index 0000000..f2cd3b8 --- /dev/null +++ b/evm/scripts/test_devnet.js @@ -0,0 +1,55 @@ +const { + CONTRACTS, + CHAIN_ID_ETH, + parseSequencesFromLogEth, + transferFromEthNative, + tryNativeToUint8Array, + getSignedVAAWithRetry, + getEmitterAddressEth, +} = require("@certusone/wormhole-sdk"); +const { + NodeHttpTransport, +} = require("@improbable-eng/grpc-web-node-http-transport"); +const addresses = require("../addresses.json"); +const { ethers } = require("ethers"); + +(async () => { + const provider = new ethers.providers.JsonRpcProvider( + "http://localhost:8545" + ); + const signer = new ethers.Wallet(process.env.MNEMONIC, provider); + // the fast transfer contract shares the same interface with the token bridge + const receipt = await transferFromEthNative( + addresses.devnet, + signer, + ethers.utils.parseEther(".00000001"), + 4, + tryNativeToUint8Array(await signer.getAddress(), CHAIN_ID_ETH), + 0 + ); + const [fastSeq, portalSeq] = parseSequencesFromLogEth( + receipt, + CONTRACTS.DEVNET.ethereum.core + ); + console.log("fast seq", fastSeq, "portal seq", portalSeq); + await getSignedVAAWithRetry( + ["http://localhost:7071"], + CHAIN_ID_ETH, + getEmitterAddressEth(addresses.devnet), + fastSeq, + { + transport: NodeHttpTransport(), + } + ); + console.log("fast", new Date().toISOString()); + await getSignedVAAWithRetry( + ["http://localhost:7071"], + CHAIN_ID_ETH, + getEmitterAddressEth(CONTRACTS.DEVNET.ethereum.token_bridge), + portalSeq, + { + transport: NodeHttpTransport(), + } + ); + console.log("portal", new Date().toISOString()); +})(); diff --git a/evm/scripts/test_testnet.js b/evm/scripts/test_testnet.js new file mode 100644 index 0000000..8e32049 --- /dev/null +++ b/evm/scripts/test_testnet.js @@ -0,0 +1,55 @@ +const { + CONTRACTS, + CHAIN_ID_ETH, + parseSequencesFromLogEth, + transferFromEthNative, + tryNativeToUint8Array, + getSignedVAAWithRetry, + getEmitterAddressEth, +} = require("@certusone/wormhole-sdk"); +const { + NodeHttpTransport, +} = require("@improbable-eng/grpc-web-node-http-transport"); +const addresses = require("../addresses.json"); +const { ethers } = require("ethers"); + +(async () => { + const provider = new ethers.providers.JsonRpcProvider( + "https://rpc.ankr.com/eth_goerli" + ); + const signer = new ethers.Wallet(process.env.MNEMONIC, provider); + // the fast transfer contract shares the same interface with the token bridge + const receipt = await transferFromEthNative( + addresses.testnet, + signer, + ethers.utils.parseEther(".00000001"), + 4, + tryNativeToUint8Array(await signer.getAddress(), CHAIN_ID_ETH), + 0 + ); + const [fastSeq, portalSeq] = parseSequencesFromLogEth( + receipt, + CONTRACTS.TESTNET.ethereum.core + ); + console.log("fast seq", fastSeq, "portal seq", portalSeq); + await getSignedVAAWithRetry( + ["https://wormhole-v2-testnet-api.certus.one"], + CHAIN_ID_ETH, + getEmitterAddressEth(addresses.testnet), + fastSeq, + { + transport: NodeHttpTransport(), + } + ); + console.log("fast", new Date().toISOString()); + await getSignedVAAWithRetry( + ["https://wormhole-v2-testnet-api.certus.one"], + CHAIN_ID_ETH, + getEmitterAddressEth(CONTRACTS.TESTNET.ethereum.token_bridge), + portalSeq, + { + transport: NodeHttpTransport(), + } + ); + console.log("portal", new Date().toISOString()); +})();