Skip to content

Commit

Permalink
fix(relayer): Out of gas (#13778)
Browse files Browse the repository at this point in the history
  • Loading branch information
cyberhorsey authored May 18, 2023
1 parent 7bffff4 commit a42a33b
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 30 deletions.
2 changes: 1 addition & 1 deletion packages/protocol/contracts/bridge/BridgeErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ abstract contract BridgeErrors {
error B_NULL_APP_ADDR();
error B_OWNER_IS_NULL();
error B_SIGNAL_NOT_RECEIVED();
error B_STATUS_MISMTACH();
error B_STATUS_MISMATCH();
error B_WRONG_CHAIN_ID();
error B_WRONG_TO_ADDRESS();
error B_ZERO_SIGNAL();
Expand Down
4 changes: 2 additions & 2 deletions packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ library LibBridgeProcess {

error B_FORBIDDEN();
error B_SIGNAL_NOT_RECEIVED();
error B_STATUS_MISMTACH();
error B_STATUS_MISMATCH();
error B_WRONG_CHAIN_ID();

/**
Expand Down Expand Up @@ -62,7 +62,7 @@ library LibBridgeProcess {
// LibBridgeRetry.sol.
bytes32 msgHash = message.hashMessage();
if (LibBridgeStatus.getMessageStatus(msgHash) != LibBridgeStatus.MessageStatus.NEW) {
revert B_STATUS_MISMTACH();
revert B_STATUS_MISMATCH();
}
// Message must have been "received" on the destChain (current chain)
address srcBridge = resolver.resolve(message.srcChainId, "bridge", false);
Expand Down
2 changes: 2 additions & 0 deletions packages/relayer/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.netrc
.env
.l1l2.env
.l2l3.env
.test.env
main
coverage.txt
Expand Down
2 changes: 1 addition & 1 deletion packages/relayer/contracts/bridge/Bridge.go

Large diffs are not rendered by default.

71 changes: 55 additions & 16 deletions packages/relayer/message/process_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,47 @@ func (p *Processor) sendProcessMessageCall(
return nil, errors.New("p.getLatestNonce")
}

gas, cost, err := p.estimateGas(ctx, event.Message, proof)
if err != nil || gas == 0 {
if err := p.hardcodeGasLimit(ctx, auth, event); err != nil {
return nil, errors.Wrap(err, "p.hardcodeGasLimit")
eventType, canonicalToken, _, err := relayer.DecodeMessageSentData(event)
if err != nil {
return nil, errors.Wrap(err, "relayer.DecodeMessageSentData")
}

var gas uint64

var cost *big.Int

var needsContractDeployment bool = false
// node is unable to estimate gas correctly for contract deployments, we need to check if the token
// is deployed, and always hardcode in this case. we need to check this before calling
// estimategas, as the node will soemtimes return a gas estimate for a contract deployment, however,
// it is incorrect and the tx will revert.
if eventType == relayer.EventTypeSendERC20 && event.Message.DestChainId.Cmp(canonicalToken.ChainId) != 0 {
// determine whether the canonical token is bridged or not on this chain
bridgedAddress, err := p.destTokenVault.CanonicalToBridged(nil, canonicalToken.ChainId, canonicalToken.Addr)
if err != nil {
return nil, errors.Wrap(err, "p.destTokenVault.IsBridgedToken")
}

if bridgedAddress == relayer.ZeroAddress {
// needs large gas limit because it has to deploy an ERC20 contract on destination
// chain. deploying ERC20 can be 2 mil by itself. we want to skip estimating gas entirely
// in this scenario.
needsContractDeployment = true
}
}

if bool(p.profitableOnly) {
profitable, err := p.isProfitable(ctx, event.Message, cost)
if err != nil || !profitable {
return nil, relayer.ErrUnprofitable
if needsContractDeployment {
auth.GasLimit = 3000000
} else {
// otherwise we can estimate gas
gas, cost, err = p.estimateGas(ctx, event.Message, proof)
// and if gas estimation failed, we just try to hardcore a value no matter what type of event,
// or whether the contract is deployed.
if err != nil || gas == 0 {
cost, err = p.hardcodeGasLimit(ctx, auth, event, eventType, canonicalToken)
if err != nil {
return nil, errors.Wrap(err, "p.hardcodeGasLimit")
}
}
}

Expand All @@ -177,6 +207,13 @@ func (p *Processor) sendProcessMessageCall(

auth.GasPrice = gasPrice

if bool(p.profitableOnly) {
profitable, err := p.isProfitable(ctx, event.Message, cost)
if err != nil || !profitable {
return nil, relayer.ErrUnprofitable
}
}

// process the message on the destination bridge.
tx, err := p.destBridge.ProcessMessage(auth, event.Message, proof)
if err != nil {
Expand All @@ -198,20 +235,17 @@ func (p *Processor) hardcodeGasLimit(
ctx context.Context,
auth *bind.TransactOpts,
event *bridge.BridgeMessageSent,
) error {
eventType, canonicalToken, _, err := relayer.DecodeMessageSentData(event)
if err != nil {
return errors.Wrap(err, "relayer.DecodeMessageSentData")
}

eventType relayer.EventType,
canonicalToken *relayer.CanonicalToken,
) (*big.Int, error) {
if eventType == relayer.EventTypeSendETH {
// eth bridges take much less gas, from 250k to 450k.
auth.GasLimit = 500000
} else {
// determine whether the canonical token is bridged or not on this chain
bridgedAddress, err := p.destTokenVault.CanonicalToBridged(nil, canonicalToken.ChainId, canonicalToken.Addr)
if err != nil {
return errors.Wrap(err, "p.destTokenVault.IsBridgedToken")
return nil, errors.Wrap(err, "p.destTokenVault.IsBridgedToken")
}

if bridgedAddress == relayer.ZeroAddress {
Expand All @@ -225,7 +259,12 @@ func (p *Processor) hardcodeGasLimit(
}
}

return nil
gasPrice, err := p.destEthClient.SuggestGasPrice(ctx)
if err != nil {
return nil, errors.Wrap(err, "p.destEthClient.SuggestGasPrice")
}

return new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(auth.GasLimit)), nil
}

func (p *Processor) setLatestNonce(nonce uint64) {
Expand Down
10 changes: 5 additions & 5 deletions packages/relayer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func WaitConfirmations(ctx context.Context, confirmer confirmer, confirmations u
}
}

func DecodeMessageSentData(event *bridge.BridgeMessageSent) (EventType, CanonicalToken, *big.Int, error) {
func DecodeMessageSentData(event *bridge.BridgeMessageSent) (EventType, *CanonicalToken, *big.Int, error) {
eventType := EventTypeSendETH

var canonicalToken CanonicalToken
Expand All @@ -130,18 +130,18 @@ func DecodeMessageSentData(event *bridge.BridgeMessageSent) (EventType, Canonica

tokenVaultABI, err := tokenVaultMD.GetAbi()
if err != nil {
return eventType, CanonicalToken{}, big.NewInt(0), errors.Wrap(err, "tokenVaultMD.GetAbi()")
return eventType, nil, big.NewInt(0), errors.Wrap(err, "tokenVaultMD.GetAbi()")
}

method, err := tokenVaultABI.MethodById(event.Message.Data[:4])
if err != nil {
return eventType, CanonicalToken{}, big.NewInt(0), errors.Wrap(err, "tokenVaultABI.MethodById")
return eventType, nil, big.NewInt(0), errors.Wrap(err, "tokenVaultABI.MethodById")
}

inputsMap := make(map[string]interface{})

if err := method.Inputs.UnpackIntoMap(inputsMap, event.Message.Data[4:]); err != nil {
return eventType, CanonicalToken{}, big.NewInt(0), errors.Wrap(err, "method.Inputs.UnpackIntoMap")
return eventType, nil, big.NewInt(0), errors.Wrap(err, "method.Inputs.UnpackIntoMap")
}

if method.Name == "receiveERC20" {
Expand All @@ -162,7 +162,7 @@ func DecodeMessageSentData(event *bridge.BridgeMessageSent) (EventType, Canonica
amount = event.Message.DepositValue
}

return eventType, canonicalToken, amount, nil
return eventType, &canonicalToken, amount, nil
}

type CanonicalToken struct {
Expand Down
6 changes: 3 additions & 3 deletions packages/relayer/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func Test_DecodeMessageSentData(t *testing.T) {
name string
event *bridge.BridgeMessageSent
wantEventType EventType
wantCanonicalToken CanonicalToken
wantCanonicalToken *CanonicalToken
wantAmount *big.Int
wantError error
}{
Expand All @@ -164,7 +164,7 @@ func Test_DecodeMessageSentData(t *testing.T) {
},
},
EventTypeSendERC20,
CanonicalToken{
&CanonicalToken{
ChainId: big.NewInt(31336),
Addr: common.HexToAddress("0xe4337137828c93D0046212ebDa8a82a24356b67B"),
Decimals: uint8(18),
Expand All @@ -184,7 +184,7 @@ func Test_DecodeMessageSentData(t *testing.T) {
},
},
EventTypeSendETH,
CanonicalToken{},
&CanonicalToken{},
big.NewInt(1),
nil,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ error B_OWNER_IS_NULL()
error B_SIGNAL_NOT_RECEIVED()
```

### B_STATUS_MISMTACH
### B_STATUS_MISMATCH

```solidity
error B_STATUS_MISMTACH()
error B_STATUS_MISMATCH()
```

### B_WRONG_CHAIN_ID
Expand Down

0 comments on commit a42a33b

Please sign in to comment.