Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GasLimit to 0 #46

Merged
merged 18 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions channel/adjudicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ type Adjudicator struct {
mu psync.Mutex
// txSender is sending the TX.
txSender accounts.Account
// gasLimit is the gas limit for all transactions to the Adjudicator.
gasLimit uint64
}

// NewAdjudicator creates a new ethereum adjudicator. The receiver is the
// on-chain address that receives withdrawals.
func NewAdjudicator(backend ContractBackend, contract common.Address, receiver common.Address, txSender accounts.Account) *Adjudicator {
func NewAdjudicator(backend ContractBackend, contract common.Address, receiver common.Address, txSender accounts.Account, gasLimit uint64) *Adjudicator {
contr, err := adjudicator.NewAdjudicator(contract, backend)
if err != nil {
panic("Could not create a new instance of adjudicator")
Expand All @@ -71,6 +73,7 @@ func NewAdjudicator(backend ContractBackend, contract common.Address, receiver c
Receiver: receiver,
txSender: txSender,
log: log.WithField("txSender", txSender.Address),
gasLimit: gasLimit,
}
}

Expand Down Expand Up @@ -153,7 +156,7 @@ func (a *Adjudicator) call(ctx context.Context, req channel.AdjudicatorReq, fn a
}
defer a.mu.Unlock()

trans, err := a.NewTransactor(ctx, GasLimit, a.txSender)
trans, err := a.NewTransactor(ctx, a.gasLimit, a.txSender)
if err != nil {
return nil, errors.WithMessage(err, "creating transactor")
}
Expand Down
2 changes: 0 additions & 2 deletions channel/contractbackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import (
)

const (
// GasLimit is the max amount of gas we want to send per transaction.
GasLimit = 1000000
// How many blocks we query into the past for events.
startBlockOffset = 100
contractBackendHeadBuffSize = 10
Expand Down
75 changes: 39 additions & 36 deletions channel/erc20_depositor.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,10 @@ import (
// ERC20Depositor deposits tokens into the `AssetHolderERC20` contract.
// It is bound to a token but can be reused to deposit multiple times.
type ERC20Depositor struct {
Token common.Address
Token common.Address
GasLimit uint64
}

// ERC20DepositorTXGasLimit is the limit of Gas that an `ERC20Depositor` will
// spend per transaction when depositing funds.
// An `IncreaseAllowance` uses ~45kGas and a `Deposit` call ~84kGas on average.
const ERC20DepositorTXGasLimit = 100000

// Return value of ERC20Depositor.NumTx.
const erc20DepositorNumTx = 2

Expand All @@ -56,26 +52,24 @@ type DepositResult struct {
}

// NewERC20Depositor creates a new ERC20Depositor.
func NewERC20Depositor(token common.Address) *ERC20Depositor {
return &ERC20Depositor{Token: token}
func NewERC20Depositor(token common.Address, gasLimit uint64) *ERC20Depositor {
return &ERC20Depositor{
Token: token,
GasLimit: gasLimit,
}
}

// Deposit approves the value to be swapped and calls DepositOnly.
func (d *ERC20Depositor) Deposit(ctx context.Context, req DepositReq) (types.Transactions, error) {
lockKey := lockKey(req.Account.Address, req.Asset.EthAddress())
lock := handleLock(lockKey)

// Bind an `ERC20` instance.
token, err := peruntoken.NewPeruntoken(d.Token, req.CB)
if err != nil {
return nil, errors.Wrapf(err, "binding ERC20 contract at: %x", d.Token)
}
callOpts := bind.CallOpts{
Pending: false,
Context: ctx,
}
var depResult DepositResult
txApproval, approvalReceived, errApproval := Approve(ctx, lock, req, token, callOpts)
txApproval, approvalReceived, errApproval := d.Approve(ctx, lock, req, callOpts)
if errApproval != nil {
return nil, errors.WithMessagef(errApproval, "approving asset: %x", req.Asset)
}
Expand All @@ -98,7 +92,7 @@ func (d *ERC20Depositor) DepositOnly(ctx context.Context, req DepositReq) (*type
return nil, errors.Wrapf(err, "binding AssetHolderERC20 contract at: %x", req.Asset)
}
// Deposit.
opts, err := req.CB.NewTransactor(ctx, ERC20DepositorTXGasLimit, req.Account)
opts, err := req.CB.NewTransactor(ctx, d.GasLimit, req.Account)
if err != nil {
return nil, errors.WithMessagef(err, "creating transactor for asset: %x", req.Asset)
}
Expand All @@ -112,37 +106,26 @@ func (*ERC20Depositor) NumTX() uint32 {
return erc20DepositorNumTx
}

// Create key from account address and asset to ensure only one deposit for an asset is performed at the same time.
func lockKey(account common.Address, asset common.Address) string {
return fmt.Sprintf("%s-%s", account.Hex(), asset.Hex())
}

// Retrieves Lock for specific key.
func handleLock(lockKey string) *sync.Mutex {
depositLocksMtx.Lock()
defer depositLocksMtx.Unlock()

if lock, exists := depositLocks[lockKey]; exists {
return lock
}

lock := &sync.Mutex{}
depositLocks[lockKey] = lock
return lock
}

// Approve locks the lock argument and Approves the requested balance + the current allowance of the requested account.
func Approve(ctx context.Context, lock *sync.Mutex, req DepositReq, token *peruntoken.Peruntoken, callOpts bind.CallOpts) (*types.Transaction, bool, error) {
func (d *ERC20Depositor) Approve(ctx context.Context, lock *sync.Mutex, req DepositReq, callOpts bind.CallOpts) (*types.Transaction, bool, error) {
lock.Lock()
defer lock.Unlock()

// Bind an `ERC20` instance.
token, err := peruntoken.NewPeruntoken(d.Token, req.CB)
if err != nil {
return nil, false, errors.Wrapf(err, "binding ERC20 contract at: %x", d.Token)
}

allowance, err := token.Allowance(&callOpts, req.Account.Address, req.Asset.EthAddress())
if err != nil {
return nil, false, errors.WithMessagef(err, "could not get Allowance for asset: %x", req.Asset)
}

result := new(big.Int).Add(req.Balance, allowance)

// Increase the allowance.
opts, err := req.CB.NewTransactor(ctx, ERC20DepositorTXGasLimit, req.Account)
opts, err := req.CB.NewTransactor(ctx, d.GasLimit, req.Account)
if err != nil {
return nil, false, errors.WithMessagef(err, "creating transactor for asset: %x", req.Asset)
}
Expand All @@ -162,6 +145,7 @@ func Approve(ctx context.Context, lock *sync.Mutex, req DepositReq, token *perun
err = cherrors.CheckIsChainNotReachableError(err)
return nil, false, errors.WithMessagef(err, "increasing allowance for asset: %x", req.Asset)
}

var approvalReceived bool
go func() {
select {
Expand All @@ -175,3 +159,22 @@ func Approve(ctx context.Context, lock *sync.Mutex, req DepositReq, token *perun
approvalReceived = <-eventReceived
return tx, approvalReceived, nil
}

// Create key from account address and asset to ensure only one deposit for an asset is performed at the same time.
func lockKey(account common.Address, asset common.Address) string {
return fmt.Sprintf("%s-%s", account.Hex(), asset.Hex())
}

// Retrieves Lock for specific key.
func handleLock(lockKey string) *sync.Mutex {
depositLocksMtx.Lock()
defer depositLocksMtx.Unlock()

if lock, exists := depositLocks[lockKey]; exists {
return lock
}

lock := &sync.Mutex{}
depositLocks[lockKey] = lock
return lock
}
17 changes: 8 additions & 9 deletions channel/eth_depositor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ import (

// ETHDepositor deposits funds into the `AssetHolderETH` contract.
// It has no state and is therefore completely reusable.
type ETHDepositor struct{}

// ETHDepositorGasLimit is the limit of Gas that an `ETHDepositor` will spend
// when depositing funds.
// A `Deposit` call uses ~47kGas on average.
const ETHDepositorGasLimit = 50000
type ETHDepositor struct {
GasLimit uint64
}

// NewETHDepositor creates a new ETHDepositor.
func NewETHDepositor() *ETHDepositor {
return &ETHDepositor{}
func NewETHDepositor(gasLimit uint64) *ETHDepositor {
return &ETHDepositor{
GasLimit: gasLimit,
}
}

// Deposit deposits ether into the ETH AssetHolder specified at the requests's
Expand All @@ -47,7 +46,7 @@ func (d *ETHDepositor) Deposit(ctx context.Context, req DepositReq) (types.Trans
if err != nil {
return nil, errors.Wrapf(err, "binding AssetHolderETH contract at: %x", req.Asset)
}
opts, err := req.CB.NewTransactor(ctx, ETHDepositorGasLimit, req.Account)
opts, err := req.CB.NewTransactor(ctx, d.GasLimit, req.Account)
if err != nil {
return nil, errors.WithMessagef(err, "creating transactor for asset: %x", req.Asset)
}
Expand Down
8 changes: 4 additions & 4 deletions channel/funder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ func newFunderSetup(rng *rand.Rand) (
accs[i] = accounts.Account{Address: ethwallet.AsEthAddr(wallettest.NewRandomAddress(rng))}
}
// Use an ETH depositor with random addresses at index 0.
depositors[0] = ethchannel.NewETHDepositor()
depositors[0] = ethchannel.NewETHDepositor(50000)
// Use an ERC20 depositor with random addresses at index 1.
token := wallettest.NewRandomAddress(rng)
depositors[1] = ethchannel.NewERC20Depositor(ethwallet.AsEthAddr(token))
depositors[1] = ethchannel.NewERC20Depositor(ethwallet.AsEthAddr(token), 100000)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gaslimit value is already defined above as txGasLimit. You can use that value.
In fact, both depositors, the NewETHDepositor and the NewERC20Depositor could use constants defined above: Instead of txGasLimit, you can set txERC20GasLimit and txETHGasLimit for both cases, with 100000 and 50000, respectively.

return funder, assets, depositors, accs
}

Expand Down Expand Up @@ -432,8 +432,8 @@ func newNFunders(
require.NoError(t, err)

funders[i] = ethchannel.NewFunder(cb)
require.True(t, funders[i].RegisterAsset(*asset1, ethchannel.NewETHDepositor(), acc))
require.True(t, funders[i].RegisterAsset(*asset2, ethchannel.NewERC20Depositor(token), acc))
require.True(t, funders[i].RegisterAsset(*asset1, ethchannel.NewETHDepositor(50000), acc))
require.True(t, funders[i].RegisterAsset(*asset2, ethchannel.NewERC20Depositor(token, 100000), acc))
}

// The challenge duration needs to be really large, since the auto-mining of
Expand Down
5 changes: 4 additions & 1 deletion channel/test/adjudicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type SimAdjudicator struct {
sb *SimulatedBackend
}

// adjustAdjudicatorGasLimit is the gas limit for the adjudicator contract.
const adjudicatorGasLimit = uint64(1000000)

// NewSimAdjudicator returns a new SimAdjudicator for the given backend. The
// backend must be a SimulatedBackend or it panics.
func NewSimAdjudicator(backend ethchannel.ContractBackend, contract common.Address, receiver common.Address, acc accounts.Account) *SimAdjudicator {
Expand All @@ -45,7 +48,7 @@ func NewSimAdjudicator(backend ethchannel.ContractBackend, contract common.Addre
panic("SimAdjudicator can only be created with a SimulatedBackend.")
}
return &SimAdjudicator{
Adjudicator: *ethchannel.NewAdjudicator(backend, contract, receiver, acc),
Adjudicator: *ethchannel.NewAdjudicator(backend, contract, receiver, acc, adjudicatorGasLimit),
sb: sb,
}
}
Expand Down
3 changes: 2 additions & 1 deletion channel/test/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
const (
defaultTxTimeout = 5 * time.Second
defaultSetupTimeout = 5 * time.Second
defaultETHGasLimit = uint64(50000)
)

type (
Expand Down Expand Up @@ -127,7 +128,7 @@ func NewSetup(t *testing.T, rng *rand.Rand, n int, blockInterval time.Duration,
txFinalityDepth,
)
s.Funders[i] = ethchannel.NewFunder(cb)
require.True(t, s.Funders[i].RegisterAsset(*s.Asset, ethchannel.NewETHDepositor(), s.Accs[i].Account))
require.True(t, s.Funders[i].RegisterAsset(*s.Asset, ethchannel.NewETHDepositor(defaultETHGasLimit), s.Accs[i].Account))
s.Adjs[i] = NewSimAdjudicator(cb, adjudicator, common.Address(*s.Recvs[i]), s.Accs[i].Account)
}

Expand Down
2 changes: 1 addition & 1 deletion channel/withdraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (a *Adjudicator) callAssetWithdraw(ctx context.Context, request channel.Adj
return nil, errors.Wrap(ctx.Err(), "context canceled while acquiring tx lock")
}
defer a.mu.Unlock()
trans, err := a.NewTransactor(ctx, GasLimit, a.txSender)
trans, err := a.NewTransactor(ctx, a.gasLimit, a.txSender)
if err != nil {
return nil, errors.WithMessagef(err, "creating transactor for asset %d", asset.assetIndex)
}
Expand Down
9 changes: 5 additions & 4 deletions client/test/multiledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ import (
)

const (
txFinalityDepth = 1
blockInterval = 300 * time.Millisecond
txFinalityDepth = 1
blockInterval = 300 * time.Millisecond
defaultETHGasLimit = uint64(50000)
)

// SetupMultiLedgerTest creates a multi-ledger test setup.
Expand Down Expand Up @@ -153,13 +154,13 @@ func setupClient(t *testing.T, rng *rand.Rand, l1, l2 testLedger, bus wire.Bus)
multiFunder := multi.NewFunder()
funderL1 := ethchannel.NewFunder(cb1)
funderL2 := ethchannel.NewFunder(cb2)
registered := funderL1.RegisterAsset(*l1.asset, ethchannel.NewETHDepositor(), acc.Account)
registered := funderL1.RegisterAsset(*l1.asset, ethchannel.NewETHDepositor(defaultETHGasLimit), acc.Account)
require.True(registered)
registered = funderL1.RegisterAsset(*l2.asset, ethchannel.NewNoOpDepositor(), acc.Account)
require.True(registered)
registered = funderL2.RegisterAsset(*l1.asset, ethchannel.NewNoOpDepositor(), acc.Account)
require.True(registered)
registered = funderL2.RegisterAsset(*l2.asset, ethchannel.NewETHDepositor(), acc.Account)
registered = funderL2.RegisterAsset(*l2.asset, ethchannel.NewETHDepositor(defaultETHGasLimit), acc.Account)
require.True(registered)
multiFunder.RegisterFunder(l1.ChainID(), funderL1)
multiFunder.RegisterFunder(l2.ChainID(), funderL2)
Expand Down
Loading