Skip to content

Commit

Permalink
Merge branch 'main' into gstuart/teleporter-release-flow
Browse files Browse the repository at this point in the history
  • Loading branch information
geoff-vball authored Jan 5, 2024
2 parents 96fc556 + 427bb54 commit 7d4081c
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 163 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ contract ERC20TokenSource is
ITokenSource,
ReentrancyGuard
{
// The address where the burned transaction fees are credited.
// Defined as BLACKHOLE_ADDRESS at
// https://github.com/ava-labs/subnet-evm/blob/e23ab058d039ff9c8469c89b139d21d52c4bd283/constants/constants.go
address public constant BURNED_TX_FEES_ADDRESS = 0x0100000000000000000000000000000000000000;
// Designated Blackhole Address for this contract. Tokens are sent here to be "burned" when
// a SourceAction.Burn message is received from the destination chain.
address public constant BURN_ADDRESS = 0x0100000000000000000000000000000000010203;
uint256 public constant MINT_NATIVE_TOKENS_REQUIRED_GAS = 100_000;
// Used to keep track of tokens burned through transactions on the destination chain. They can
// be reported to this contract to burn an equivalent number of tokens on this chain.
Expand Down Expand Up @@ -174,7 +173,7 @@ contract ERC20TokenSource is
*/
function _burnTokens(uint256 amount) private {
emit BurnTokens(amount);
SafeERC20.safeTransfer(IERC20(erc20ContractAddress), BURNED_TX_FEES_ADDRESS, amount);
SafeERC20.safeTransfer(IERC20(erc20ContractAddress), BURN_ADDRESS, amount);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ contract NativeTokenDestination is
// Designated Blackhole Address for this contract. Tokens are sent here to be "burned" before
// sending an unlock message to the source chain. Different from the burned tx fee address so
// they can be tracked separately.
address public constant BURN_FOR_TRANSFER_ADDRESS = 0x0100000000000000000000000000000000000001;
address public constant BURN_FOR_TRANSFER_ADDRESS = 0x0100000000000000000000000000000000010203;

INativeMinter public constant NATIVE_MINTER =
INativeMinter(0x0200000000000000000000000000000000000001);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ contract NativeTokenSource is
ITokenSource,
ReentrancyGuard
{
// The address where the burned transaction fees are credited.
// Defined as BLACKHOLE_ADDRESS at
// https://github.com/ava-labs/subnet-evm/blob/e23ab058d039ff9c8469c89b139d21d52c4bd283/constants/constants.go
address public constant BURNED_TX_FEES_ADDRESS = 0x0100000000000000000000000000000000000000;
// Designated Blackhole Address for this contract. Tokens are sent here to be "burned" when
// a SourceAction.Burn message is received from the destination chain.
address public constant BURN_ADDRESS = 0x0100000000000000000000000000000000010203;
uint256 public constant MINT_NATIVE_TOKENS_REQUIRED_GAS = 100_000;
// Used to keep track of tokens burned through transactions on the destination chain. They can
// be reported to this contract to burn an equivalent number of tokens on this chain.
Expand Down Expand Up @@ -163,7 +162,7 @@ contract NativeTokenSource is
*/
function _burnTokens(uint256 amount) private {
emit BurnTokens(amount);
Address.sendValue(payable(BURNED_TX_FEES_ADDRESS), amount);
Address.sendValue(payable(BURN_ADDRESS), amount);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ contract ERC20TokenSourceTest is NativeTokenBridgeTest {
);

assertEq(burnedTxFees, erc20TokenSource.destinationBurnedTotal());
assertEq(burnedTxFees, mockERC20.balanceOf(erc20TokenSource.BURNED_TX_FEES_ADDRESS()));
assertEq(burnedTxFees, mockERC20.balanceOf(erc20TokenSource.BURN_ADDRESS()));

vm.prank(MOCK_TELEPORTER_MESSENGER_ADDRESS);
erc20TokenSource.receiveTeleporterMessage(
Expand All @@ -129,7 +129,7 @@ contract ERC20TokenSourceTest is NativeTokenBridgeTest {
);

assertEq(burnedTxFees, erc20TokenSource.destinationBurnedTotal());
assertEq(burnedTxFees, mockERC20.balanceOf(erc20TokenSource.BURNED_TX_FEES_ADDRESS()));
assertEq(burnedTxFees, mockERC20.balanceOf(erc20TokenSource.BURN_ADDRESS()));

emit BurnTokens(additionalTxFees);

Expand All @@ -142,8 +142,7 @@ contract ERC20TokenSourceTest is NativeTokenBridgeTest {

assertEq(burnedTxFees + additionalTxFees, erc20TokenSource.destinationBurnedTotal());
assertEq(
burnedTxFees + additionalTxFees,
mockERC20.balanceOf(erc20TokenSource.BURNED_TX_FEES_ADDRESS())
burnedTxFees + additionalTxFees, mockERC20.balanceOf(erc20TokenSource.BURN_ADDRESS())
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ contract NativeTokenSourceTest is NativeTokenBridgeTest {
);

assertEq(burnedTxFees, nativeTokenSource.destinationBurnedTotal());
assertEq(burnedTxFees, nativeTokenSource.BURNED_TX_FEES_ADDRESS().balance);
assertEq(burnedTxFees, nativeTokenSource.BURN_ADDRESS().balance);

vm.prank(MOCK_TELEPORTER_MESSENGER_ADDRESS);
nativeTokenSource.receiveTeleporterMessage(
Expand All @@ -136,7 +136,7 @@ contract NativeTokenSourceTest is NativeTokenBridgeTest {
);

assertEq(burnedTxFees, nativeTokenSource.destinationBurnedTotal());
assertEq(burnedTxFees, nativeTokenSource.BURNED_TX_FEES_ADDRESS().balance);
assertEq(burnedTxFees, nativeTokenSource.BURN_ADDRESS().balance);

emit BurnTokens(additionalTxFees);

Expand All @@ -148,9 +148,7 @@ contract NativeTokenSourceTest is NativeTokenBridgeTest {
);

assertEq(burnedTxFees + additionalTxFees, nativeTokenSource.destinationBurnedTotal());
assertEq(
burnedTxFees + additionalTxFees, nativeTokenSource.BURNED_TX_FEES_ADDRESS().balance
);
assertEq(burnedTxFees + additionalTxFees, nativeTokenSource.BURN_ADDRESS().balance);
}

function testZeroTeleporterAddress() public {
Expand Down
154 changes: 90 additions & 64 deletions tests/flows/erc20_to_native_token_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,17 @@ func ERC20ToNativeTokenBridge(network interfaces.LocalNetwork) {
deployerAddress = common.HexToAddress("0x539447ab8Be7e927bE8E005663C81ff2AE951337")
tokenReceiverAddress = common.HexToAddress("0x4444444444444444444444444444444444444444")
burnedTxFeeAddress = common.HexToAddress("0x0100000000000000000000000000000000000000")
burnAddressSource = common.HexToAddress("0x0100000000000000000000000000000000010203")

emptyDestFeeInfo = nativetokendestination.TeleporterFeeInfo{
FeeTokenAddress: common.Address{},
Amount: common.Big0,
}
)

// sourceSubnet := network.GetPrimaryNetworkInfo() // TODO: Integrate the C-Chain
sourceSubnet, destSubnet := utils.GetTwoSubnets(network)
sourceSubnet := network.GetPrimaryNetworkInfo()
_, destSubnet := utils.GetTwoSubnets(network)
_, fundedKey := network.GetFundedAccountInfo()

// Info we need to calculate for the test
deployerPK, err := crypto.HexToECDSA(deployerKeyStr)
Expand All @@ -59,45 +61,71 @@ func ERC20ToNativeTokenBridge(network interfaces.LocalNetwork) {
Expect(err).Should(BeNil())
log.Info("Example ERC20 Contract Address: " + exampleERC20ContractAddress.Hex())

// Deploy the contracts
// Both contracts in this test will be deployed to 0x3405506b3711859c5070949ed9b700c7ba7bf750,
// though they do not necessarily have to be deployed at the same address, each contract needs
// to know the address of the other.
// The nativeTokenDestination contract must be added to "adminAddresses" of "contractNativeMinterConfig"
// in the genesis file for the subnet. This will allow it to call the native minter precompile.
erc20TokenSourceAbi, err := erc20tokensource.ERC20TokenSourceMetaData.GetAbi()
Expect(err).Should(BeNil())
utils.DeployContract(
ctx,
ERC20TokenSourceByteCodeFile,
deployerPK,
sourceSubnet,
erc20TokenSourceAbi,
sourceSubnet.TeleporterRegistryAddress,
destSubnet.BlockchainID,
bridgeContractAddress,
exampleERC20ContractAddress,
)
{
// Fund the deployer address with sufficient native tokens (100 eth = 1e20 wei) on the source chain to deploy the
// contract and send a number of transfer transactions.
sourceFundingAmount := utils.BigIntMul(big.NewInt(1e15), big.NewInt(1e5))
utils.SendNativeTransfer(
ctx,
sourceSubnet,
fundedKey,
deployerAddress,
sourceFundingAmount,
)

nativeTokenDestinationAbi, err := nativetokendestination.NativeTokenDestinationMetaData.GetAbi()
Expect(err).Should(BeNil())
utils.DeployContract(
ctx,
NativeTokenDestinationByteCodeFile,
deployerPK,
destSubnet,
nativeTokenDestinationAbi,
destSubnet.TeleporterRegistryAddress,
sourceSubnet.BlockchainID,
bridgeContractAddress,
initialReserveImbalance,
)
// On the destination chain, the deployer address needs valueToReturn native tokens to attempt (and fail)
// to send tokens before the bridge contracts are collateralized. It also needs some extra for gas costs,
// so we send valueToReturn*2
utils.SendNativeTransfer(
ctx,
destSubnet,
fundedKey,
deployerAddress,
utils.BigIntMul(valueToReturn, big.NewInt(2)),
)
}

exampleERC20Abi, err := exampleerc20.ExampleERC20MetaData.GetAbi()
Expect(err).Should(BeNil())
utils.DeployContract(ctx, ExampleERC20ByteCodeFile, deployerPK, sourceSubnet, exampleERC20Abi)
{
// Deploy the contracts
// Both contracts in this test will be deployed to 0x3405506b3711859c5070949ed9b700c7ba7bf750,
// though they do not necessarily have to be deployed at the same address, each contract needs
// to know the address of the other.
// The nativeTokenDestination contract must be added to "adminAddresses" of "contractNativeMinterConfig"
// in the genesis file for the subnet. This will allow it to call the native minter precompile.
erc20TokenSourceAbi, err := erc20tokensource.ERC20TokenSourceMetaData.GetAbi()
Expect(err).Should(BeNil())
utils.DeployContract(
ctx,
ERC20TokenSourceByteCodeFile,
deployerPK,
sourceSubnet,
erc20TokenSourceAbi,
sourceSubnet.TeleporterRegistryAddress,
destSubnet.BlockchainID,
bridgeContractAddress,
exampleERC20ContractAddress,
)

log.Info("Finished deploying contracts")
nativeTokenDestinationAbi, err := nativetokendestination.NativeTokenDestinationMetaData.GetAbi()
Expect(err).Should(BeNil())
utils.DeployContract(
ctx,
NativeTokenDestinationByteCodeFile,
deployerPK,
destSubnet,
nativeTokenDestinationAbi,
destSubnet.TeleporterRegistryAddress,
sourceSubnet.BlockchainID,
bridgeContractAddress,
initialReserveImbalance,
)

exampleERC20Abi, err := exampleerc20.ExampleERC20MetaData.GetAbi()
Expect(err).Should(BeNil())
utils.DeployContract(ctx, ExampleERC20ByteCodeFile, deployerPK, sourceSubnet, exampleERC20Abi)

log.Info("Finished deploying contracts")
}

// Create abi objects to call the contract with
nativeTokenDestination, err := nativetokendestination.NewNativeTokenDestination(
Expand Down Expand Up @@ -136,18 +164,17 @@ func ERC20ToNativeTokenBridge(network interfaces.LocalNetwork) {

checkReserveImbalance(initialReserveImbalance, nativeTokenDestination)

destChainReceipt :=
sendERC20TokensToDestination(
ctx,
network,
valueToSend,
deployerPK,
tokenReceiverAddress,
sourceSubnet,
destSubnet,
erc20TokenSource,
common.Big0,
)
destChainReceipt := sendERC20TokensToDestination(
ctx,
network,
valueToSend,
deployerPK,
tokenReceiverAddress,
sourceSubnet,
destSubnet,
erc20TokenSource,
common.Big0,
)

collateralEvent, err := utils.GetEventFromLogs(
destChainReceipt.Logs,
Expand Down Expand Up @@ -232,18 +259,17 @@ func ERC20ToNativeTokenBridge(network interfaces.LocalNetwork) {

{
// Transfer tokens B -> A
sourceChainReceipt :=
sendTokensToSource(
ctx,
network,
valueToReturn,
deployerPK,
tokenReceiverAddress,
sourceSubnet,
destSubnet,
nativeTokenDestination,
emptyDestFeeInfo,
)
sourceChainReceipt := sendTokensToSource(
ctx,
network,
valueToReturn,
deployerPK,
tokenReceiverAddress,
sourceSubnet,
destSubnet,
nativeTokenDestination,
emptyDestFeeInfo,
)

checkUnlockERC20Event(
sourceChainReceipt.Logs,
Expand Down Expand Up @@ -285,7 +311,7 @@ func ERC20ToNativeTokenBridge(network interfaces.LocalNetwork) {
Expect(err).Should(BeNil())
utils.ExpectBigEqual(reportEvent.BurnAddressBalance, burnedTxFeesBalanceDest)

burnedTxFeesBalanceSource, err := exampleERC20.BalanceOf(nil, burnedTxFeeAddress)
burnedTxFeesBalanceSource, err := exampleERC20.BalanceOf(nil, burnAddressSource)
Expect(err).Should(BeNil())
utils.ExpectBigEqual(burnedTxFeesBalanceSource, common.Big0)

Expand All @@ -298,7 +324,7 @@ func ERC20ToNativeTokenBridge(network interfaces.LocalNetwork) {
Expect(err).Should(BeNil())
utils.ExpectBigEqual(burnedTxFeesBalanceDest, burnEvent.Amount)

burnedTxFeesBalanceSource2, err := exampleERC20.BalanceOf(nil, burnedTxFeeAddress)
burnedTxFeesBalanceSource2, err := exampleERC20.BalanceOf(nil, burnAddressSource)
Expect(err).Should(BeNil())
utils.ExpectBigEqual(burnedTxFeesBalanceSource2, burnEvent.Amount)
}
Expand Down
Loading

0 comments on commit 7d4081c

Please sign in to comment.