Skip to content

Commit

Permalink
impl IFuntoken.balance, IFunToken.bankBalance
Browse files Browse the repository at this point in the history
  • Loading branch information
Unique-Divine committed Nov 6, 2024
1 parent 3aef202 commit d349166
Show file tree
Hide file tree
Showing 19 changed files with 592 additions and 92 deletions.
104 changes: 104 additions & 0 deletions x/evm/embeds/artifacts/contracts/IFunToken.sol/IFunToken.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,110 @@
"contractName": "IFunToken",
"sourceName": "contracts/IFunToken.sol",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "who",
"type": "address"
},
{
"internalType": "address",
"name": "funtoken",
"type": "address"
}
],
"name": "balance",
"outputs": [
{
"internalType": "uint256",
"name": "erc20Balance",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "bankBalance",
"type": "uint256"
},
{
"components": [
{
"internalType": "address",
"name": "erc20",
"type": "address"
},
{
"internalType": "string",
"name": "bankDenom",
"type": "string"
}
],
"internalType": "struct IFunToken.FunToken",
"name": "token",
"type": "tuple"
},
{
"components": [
{
"internalType": "address",
"name": "ethAddr",
"type": "address"
},
{
"internalType": "string",
"name": "bech32Addr",
"type": "string"
}
],
"internalType": "struct IFunToken.NibiruAccount",
"name": "whoAddrs",
"type": "tuple"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "who",
"type": "address"
},
{
"internalType": "string",
"name": "bankDenom",
"type": "string"
}
],
"name": "bankBalance",
"outputs": [
{
"internalType": "uint256",
"name": "bankBalance",
"type": "uint256"
},
{
"components": [
{
"internalType": "address",
"name": "ethAddr",
"type": "address"
},
{
"internalType": "string",
"name": "bech32Addr",
"type": "string"
}
],
"internalType": "struct IFunToken.NibiruAccount",
"name": "whoAddrs",
"type": "tuple"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

33 changes: 29 additions & 4 deletions x/evm/embeds/contracts/IFunToken.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;

address constant FUNTOKEN_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000800;
IFunToken constant FUNTOKEN_PRECOMPILE = IFunToken(FUNTOKEN_PRECOMPILE_ADDRESS);

/// @dev Implements the functionality for sending ERC20 tokens and bank
/// coins to various Nibiru accounts using either the Nibiru Bech32 address
/// using the "FunToken" mapping between the ERC20 and bank.
Expand All @@ -15,10 +18,32 @@ interface IFunToken {
function sendToBank(
address erc20,
uint256 amount,
string memory to
string calldata to
) external returns (uint256 sentAmount);
}

address constant FUNTOKEN_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000800;
struct NibiruAccount {
address ethAddr;
string bech32Addr;
}
struct FunToken {
address erc20;
string bankDenom;
}

IFunToken constant FUNTOKEN_PRECOMPILE = IFunToken(FUNTOKEN_PRECOMPILE_ADDRESS);
function balance(
address who,
address funtoken
)
external
returns (
uint256 erc20Balance,
uint256 bankBalance,
FunToken memory token,
NibiruAccount memory whoAddrs
);

function bankBalance(
address who,
string calldata bankDenom
) external returns (uint256 bankBalance, NibiruAccount memory whoAddrs);
}
21 changes: 21 additions & 0 deletions x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,25 @@ contract TestNativeSendThenPrecompileSend {
)
);
}

function justPrecompileSend(
string memory precompileRecipient,
uint256 precompileAmount
) public {
uint256 sentAmount = FUNTOKEN_PRECOMPILE.sendToBank(
erc20,
precompileAmount,
precompileRecipient
);
require(
sentAmount == precompileAmount,
string.concat(
"IFunToken.sendToBank succeeded but transferred the wrong amount",
"sentAmount ",
Strings.toString(sentAmount),
"expected ",
Strings.toString(precompileAmount)
)
);
}
}
12 changes: 12 additions & 0 deletions x/evm/evmtest/erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,15 @@ func AssertBankBalanceEqualWithDescription(
assert.Equalf(t, expectedBalance.String(), actualBalance.String(),
"expected %s, got %s", expectedBalance, actualBalance, errSuffix)
}

const (
// FunTokenGasLimitSendToEvm consists of gas for 3 calls:
// 1. transfer erc20 from sender to module
// ~60_000 gas for regular erc20 transfer (our own ERC20Minter contract)
// could be higher for user created contracts, let's cap with 200_000
// 2. mint native coin (made from erc20) or burn erc20 token (made from coin)
// ~60_000 gas for either mint or burn
// 3. send from module to account:
// ~65_000 gas (bank send)
FunTokenGasLimitSendToEvm uint64 = 400_000
)
66 changes: 56 additions & 10 deletions x/evm/keeper/funtoken_from_coin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() {
alice.EthAddr,
&precompile.PrecompileAddr_FunToken,
true,
precompile.FunTokenGasLimitBankSend,
evmtest.FunTokenGasLimitSendToEvm,
"sendToBank",
funToken.Erc20Addr.Address,
big.NewInt(10),
Expand Down Expand Up @@ -262,7 +262,7 @@ func (s *FunTokenFromCoinSuite) TestConvertCoinToEvmAndBack() {
alice.EthAddr,
&precompile.PrecompileAddr_FunToken,
true,
precompile.FunTokenGasLimitBankSend,
evmtest.FunTokenGasLimitSendToEvm,
"sendToBank",
funToken.Erc20Addr.Address,
big.NewInt(10),
Expand Down Expand Up @@ -353,6 +353,9 @@ func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() {
}.Assert(s.T(), deps)

s.T().Log("call test contract")
deps.ResetGasMeter()
newSendAmtSendToBank := new(big.Int).Quo(sendAmt, big.NewInt(2))
newSendAmtEvmTransfer := evm.NativeToWei(newSendAmtSendToBank)
evmResp, err := deps.EvmKeeper.CallContract(
deps.Ctx,
embeds.SmartContract_TestNativeSendThenPrecompileSendJson.ABI,
Expand All @@ -362,26 +365,68 @@ func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() {
10_000_000, // 100% sufficient gas
"nativeSendThenPrecompileSend",
[]any{
alice.EthAddr,
evm.NativeToWei(sendAmt), // native send uses wei units
alice.NibiruAddr.String(),
sendAmt, // amount for precompile sendToBank
alice.EthAddr, // nativeRecipient
newSendAmtEvmTransfer, // nativeAmount (wei units)
alice.NibiruAddr.String(), // precompileRecipient
newSendAmtSendToBank, // precompileAmount
}...,
)
s.Require().NoError(err)
s.Empty(evmResp.VmError)
gasUsedFor2Ops := evmResp.GasUsed

evmtest.FunTokenBalanceAssert{
FunToken: funtoken,
Account: alice.EthAddr,
BalanceBank: new(big.Int).Mul(
newSendAmtSendToBank, big.NewInt(2)),
BalanceERC20: big.NewInt(0),
}.Assert(s.T(), deps)

evmtest.FunTokenBalanceAssert{
FunToken: funtoken,
Account: alice.EthAddr,
BalanceBank: new(big.Int).Mul(sendAmt, big.NewInt(2)),
Account: testContractAddr,
BalanceBank: big.NewInt(5),
BalanceERC20: big.NewInt(5),
}.Assert(s.T(), deps)

evmtest.FunTokenBalanceAssert{
FunToken: funtoken,
Account: evm.EVM_MODULE_ADDRESS,
BalanceBank: big.NewInt(5),
BalanceERC20: big.NewInt(0),
}.Assert(s.T(), deps)

deps.ResetGasMeter()
evmResp, err = deps.EvmKeeper.CallContract(
deps.Ctx,
embeds.SmartContract_TestNativeSendThenPrecompileSendJson.ABI,
deps.Sender.EthAddr,
&testContractAddr,
true,
10_000_000, // 100% sufficient gas
"justPrecompileSend",
[]any{
alice.NibiruAddr.String(), // precompileRecipient
newSendAmtSendToBank, // precompileAmount
}...,
)
s.Require().NoError(err)
s.Empty(evmResp.VmError)
gasUsedFor1Op := evmResp.GasUsed

evmtest.FunTokenBalanceAssert{
FunToken: funtoken,
Account: alice.EthAddr,
BalanceBank: new(big.Int).Mul(
newSendAmtSendToBank, big.NewInt(3)),
BalanceERC20: big.NewInt(0),
}.Assert(s.T(), deps)

evmtest.FunTokenBalanceAssert{
FunToken: funtoken,
Account: testContractAddr,
BalanceBank: big.NewInt(0),
BalanceBank: big.NewInt(5),
BalanceERC20: big.NewInt(0),
}.Assert(s.T(), deps)

Expand All @@ -391,6 +436,7 @@ func (s *FunTokenFromCoinSuite) TestNativeSendThenPrecompileSend() {
BalanceBank: big.NewInt(0),
BalanceERC20: big.NewInt(0),
}.Assert(s.T(), deps)
s.Require().Greater(gasUsedFor2Ops, gasUsedFor1Op, "2 operations should consume more gas")
}

// TestERC20TransferThenPrecompileSend
Expand Down Expand Up @@ -553,7 +599,7 @@ func (s *FunTokenFromCoinSuite) TestPrecompileSelfCallRevert() {
deps.Sender.EthAddr,
&testContractAddr,
true,
precompile.FunTokenGasLimitBankSend,
evmtest.FunTokenGasLimitSendToEvm,
"selfCallTransferFunds",
alice.EthAddr,
evm.NativeToWei(big.NewInt(1e6)), // native send uses wei units,
Expand Down
6 changes: 3 additions & 3 deletions x/evm/keeper/funtoken_from_erc20_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() {
deps.Sender.EthAddr,
&precompile.PrecompileAddr_FunToken,
true,
precompile.FunTokenGasLimitBankSend,
evmtest.FunTokenGasLimitSendToEvm,
"sendToBank",
deployResp.ContractAddr,
big.NewInt(1),
Expand All @@ -244,7 +244,7 @@ func (s *FunTokenFromErc20Suite) TestSendFromEvmToBank() {
deps.Sender.EthAddr,
&precompile.PrecompileAddr_FunToken,
true,
precompile.FunTokenGasLimitBankSend,
evmtest.FunTokenGasLimitSendToEvm,
"sendToBank",
deployResp.ContractAddr,
big.NewInt(70_000),
Expand Down Expand Up @@ -376,7 +376,7 @@ func (s *FunTokenFromErc20Suite) TestFunTokenFromERC20MaliciousTransfer() {
deps.Sender.EthAddr,
&precompile.PrecompileAddr_FunToken,
true,
precompile.FunTokenGasLimitBankSend,
evmtest.FunTokenGasLimitSendToEvm,
"sendToBank",
deployResp.ContractAddr,
big.NewInt(1),
Expand Down
9 changes: 0 additions & 9 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"math/big"

"cosmossdk.io/math"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
gethparams "github.com/ethereum/go-ethereum/params"
Expand Down Expand Up @@ -116,14 +115,6 @@ func (k *Keeper) AddToBlockGasUsed(
return blockGasUsed, nil
}

// GetMinGasUsedMultiplier - value from 0 to 1
// When executing evm msg, user specifies gasLimit.
// If the gasLimit is X times higher than the actual gasUsed then
// we update gasUsed = max(gasUsed, gasLimit * minGasUsedPct)
func (k Keeper) GetMinGasUsedMultiplier(ctx sdk.Context) math.LegacyDec {
return math.LegacyNewDecWithPrec(50, 2) // 50%
}

// BaseFeeMicronibiPerGas returns the gas base fee in units of the EVM denom. Note
// that this function is currently constant/stateless.
func (k Keeper) BaseFeeMicronibiPerGas(_ sdk.Context) *big.Int {
Expand Down
Loading

0 comments on commit d349166

Please sign in to comment.