Skip to content
This repository has been archived by the owner on Dec 3, 2024. It is now read-only.

Commit

Permalink
Merge branch 'basic-send-receive' into nativeTokenSource
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Lam committed Mar 14, 2024
2 parents c4ae500 + dcb843a commit 4693140
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 35 deletions.
2 changes: 1 addition & 1 deletion abi-bindings/go/ERC20Destination/ERC20Destination.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion abi-bindings/go/ERC20Source/ERC20Source.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion abi-bindings/go/NativeTokenSource/NativeTokenSource.go

Large diffs are not rendered by default.

25 changes: 20 additions & 5 deletions contracts/src/TeleporterTokenDestination.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ abstract contract TeleporterTokenDestination is
/// @notice The ERC20 token this contract uses to pay for Teleporter fees.
address public immutable feeTokenAddress;

// TODO: these are values brought from the example ERC20Bridge contract.
// Need to figure out appropriate values.
uint256 public constant SEND_TOKENS_REQUIRED_GAS = 300_000;

/**
Expand All @@ -60,25 +62,38 @@ abstract contract TeleporterTokenDestination is
* @notice Sends tokens to the specified destination token bridge instance.
*
* @dev Burns the bridged amount, and uses Teleporter to send a cross chain message.
* Tokens can be sent to the same blockchain this bridge instance is deployed on,
* to another destination bridge instance.
* Requirements:
*
* - `input.destinationBlockchainID` cannot be the same as the current blockchainID
* - `input.destinationBridgeAddress` cannot be the zero address
* - `input.recipient` cannot be the zero address
* - `amount` must be greater than 0
* - `amount` must be greater than `input.primaryFee`
*/
function _send(SendTokensInput calldata input, uint256 amount) internal virtual {
require(
input.destinationBlockchainID != blockchainID,
"TeleporterTokenDestination: cannot bridge to same chain"
);
require(
input.destinationBridgeAddress != address(0),
"TeleporterTokenDestination: zero destination bridge address"
);
require(input.recipient != address(0), "TeleporterTokenDestination: zero recipient address");

// If the destination blockchain is the source bridge instance's blockchain,
// the destination bridge address must match the token source address.
if (input.destinationBlockchainID == sourceBlockchainID) {
require(
input.destinationBridgeAddress == tokenSourceAddress,
"TeleporterTokenDestination: invalid destination bridge address"
);
}

if (input.destinationBlockchainID == blockchainID) {
require(
input.destinationBridgeAddress != address(this),
"TeleporterTokenDestination: invalid destination bridge address"
);
}

// Deposit the funds sent from the user to the bridge,
// and set to adjusted amount after deposit
amount = _deposit(amount);
Expand Down
5 changes: 4 additions & 1 deletion contracts/src/TeleporterTokenSource.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ abstract contract TeleporterTokenSource is ITeleporterTokenBridge, TeleporterOwn
=> mapping(address destinationBridgeAddress => uint256 balance)
) public bridgedBalances;

// TODO: these are values brought from the example ERC20Bridge contract.
// Need to figure out appropriate values.
uint256 public constant SEND_TOKENS_REQUIRED_GAS = 300_000;

/**
Expand Down Expand Up @@ -145,7 +147,8 @@ abstract contract TeleporterTokenSource is ITeleporterTokenBridge, TeleporterOwn
// Decrement the bridge balance by the unwrap amount
bridgedBalances[sourceBlockchainID][originSenderAddress] = senderBalance - amount;

// decrement totalAmount from bridge balance
// If the final destination of the transfer is this source bridge instance, withdraw the tokens.abi
// Otherwise, perform a multihop transfer to the input destination bridge instance.
if (input.destinationBlockchainID == blockchainID) {
require(
input.destinationBridgeAddress == address(this),
Expand Down
38 changes: 30 additions & 8 deletions contracts/test/TeleporterTokenDestinationTests.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,6 @@ contract TeleporterTokenDestinationTest is Test {
/**
* Send tokens unit tests
*/

function testSendToSameChain() public {
SendTokensInput memory input = _createDefaultSendTokensInput();
input.destinationBlockchainID = DEFAULT_DESTINATION_BLOCKCHAIN_ID;
vm.expectRevert(_formatTokenDestinationErrorMessage("cannot bridge to same chain"));
app.send(input, 0);
}

function testZeroDestinationBridge() public {
SendTokensInput memory input = _createDefaultSendTokensInput();
input.destinationBridgeAddress = address(0);
Expand All @@ -124,6 +116,21 @@ contract TeleporterTokenDestinationTest is Test {
app.send(input, 0);
}

function testInvalidSendingBackToSourceBlockchain() public {
SendTokensInput memory input = _createDefaultSendTokensInput();
input.destinationBridgeAddress = address(this);
vm.expectRevert(_formatTokenDestinationErrorMessage("invalid destination bridge address"));
app.send(input, 0);
}

function testSendingToSameInstance() public {
SendTokensInput memory input = _createDefaultSendTokensInput();
input.destinationBlockchainID = app.blockchainID();
input.destinationBridgeAddress = address(app);
vm.expectRevert(_formatTokenDestinationErrorMessage("invalid destination bridge address"));
app.send(input, 0);
}

function testZeroSendAmount() public {
vm.expectRevert(_formatTokenDestinationErrorMessage("zero send amount"));
app.send(_createDefaultSendTokensInput(), 0);
Expand All @@ -148,6 +155,21 @@ contract TeleporterTokenDestinationTest is Test {
_sendSuccess(amount, primaryFee);
}

function testSendToSameBlockchainDifferentDestination() public {
// Send a transfer to the same app itself
uint256 amount = 2;
SendTokensInput memory input = _createDefaultSendTokensInput();
input.destinationBlockchainID = app.blockchainID();
input.destinationBridgeAddress = address(this);

uint256 bridgedAmount = amount - input.primaryFee;
_checkExpectedTeleporterCalls(input, bridgedAmount);

vm.expectEmit(true, true, true, true, address(app));
emit SendTokens(_MOCK_MESSAGE_ID, address(this), bridgedAmount);
app.send(input, amount);
}

/**
* Receive tokens unit tests
*/
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/ava-labs/teleporter-token-bridge
go 1.21

require (
github.com/ava-labs/avalanchego v1.11.1
github.com/ava-labs/subnet-evm v0.6.1
github.com/ava-labs/teleporter v1.0.0
github.com/ethereum/go-ethereum v1.12.0
Expand All @@ -16,7 +17,6 @@ require (
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/VictoriaMetrics/fastcache v1.10.0 // indirect
github.com/ava-labs/avalanche-network-runner v1.7.6 // indirect
github.com/ava-labs/avalanchego v1.11.1 // indirect
github.com/ava-labs/coreth v0.13.0-rc.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
Expand Down Expand Up @@ -134,7 +134,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1016,8 +1016,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
1 change: 1 addition & 0 deletions scripts/abi_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ source $TELEPORTER_PATH/scripts/utils.sh

setARCH

# Contract names to generate Go bindings for
DEFAULT_CONTRACT_LIST="ERC20Source ERC20Destination NativeTokenSource"

CONTRACT_LIST=
Expand Down
6 changes: 3 additions & 3 deletions tests/flows/basic_erc20_send_receive.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func BasicERC20SendReceive(network interfaces.Network) {
fundedKey,
subnetBInfo,
fundedAddress,
subnetAInfo,
subnetAInfo.BlockchainID,
erc20SourceAddress,
tokenName,
tokenSymbol,
Expand Down Expand Up @@ -104,9 +104,9 @@ func BasicERC20SendReceive(network interfaces.Network) {
utils.CheckERC20DestinationWithdrawal(
ctx,
erc20Destination,
receipt,
recipientAddress,
bridgedAmount,
receipt,
)

// Check that the recipient received the tokens
Expand Down Expand Up @@ -158,9 +158,9 @@ func BasicERC20SendReceive(network interfaces.Network) {
ctx,
erc20SourceAddress,
sourceToken,
receipt,
recipientAddress,
bridgedAmount,
receipt,
)

// Check that the recipient received the tokens
Expand Down
22 changes: 11 additions & 11 deletions tests/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"crypto/ecdsa"
"math/big"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/subnet-evm/accounts/abi/bind"
"github.com/ava-labs/subnet-evm/core/types"
erc20destination "github.com/ava-labs/teleporter-token-bridge/abi-bindings/go/ERC20Destination"
Expand Down Expand Up @@ -53,12 +54,11 @@ func DeployERC20Destination(
senderKey *ecdsa.PrivateKey,
subnet interfaces.SubnetTestInfo,
teleporterManager common.Address,
sourceSubnet interfaces.SubnetTestInfo,
sourceBlockchainID ids.ID,
tokenSourceAddress common.Address,
tokenName string,
tokenSymbol string,
tokenDecimals uint8,

) (common.Address, *erc20destination.ERC20Destination) {
opts, err := bind.NewKeyedTransactorWithChainID(
senderKey,
Expand All @@ -70,7 +70,7 @@ func DeployERC20Destination(
subnet.RPCClient,
subnet.TeleporterRegistryAddress,
teleporterManager,
sourceSubnet.BlockchainID,
sourceBlockchainID,
tokenSourceAddress,
tokenName,
tokenSymbol,
Expand Down Expand Up @@ -220,27 +220,27 @@ func CheckERC20SourceWithdrawal(
ctx context.Context,
erc20SourceAddress common.Address,
sourceToken *exampleerc20.ExampleERC20,
recipientAddress common.Address,
amount *big.Int,
receipt *types.Receipt,
expectedRecipientAddress common.Address,
expectedAmount *big.Int,
) {
sourceTransferEvent, err := teleporterUtils.GetEventFromLogs(receipt.Logs, sourceToken.ParseTransfer)
Expect(err).Should(BeNil())
Expect(sourceTransferEvent.From).Should(Equal(erc20SourceAddress))
Expect(sourceTransferEvent.To).Should(Equal(recipientAddress))
Expect(sourceTransferEvent.Value).Should(Equal(amount))
Expect(sourceTransferEvent.To).Should(Equal(expectedRecipientAddress))
Expect(sourceTransferEvent.Value).Should(Equal(expectedAmount))
}

func CheckERC20DestinationWithdrawal(
ctx context.Context,
erc20Destination *erc20destination.ERC20Destination,
recipientAddress common.Address,
amount *big.Int,
receipt *types.Receipt,
expectedRecipientAddress common.Address,
expectedAmount *big.Int,
) {
transferEvent, err := teleporterUtils.GetEventFromLogs(receipt.Logs, erc20Destination.ParseTransfer)
Expect(err).Should(BeNil())
Expect(transferEvent.From).Should(Equal(common.Address{}))
Expect(transferEvent.To).Should(Equal(recipientAddress))
Expect(transferEvent.Value).Should(Equal(amount))
Expect(transferEvent.To).Should(Equal(expectedRecipientAddress))
Expect(transferEvent.Value).Should(Equal(expectedAmount))
}

0 comments on commit 4693140

Please sign in to comment.