Add InterchainGasPaymaster (#285)
* Add InterchainGasPaymaster * Underscore leaf index parameter * Add event section commentpull/292/head
parent
a9b509e973
commit
fad3739409
@ -0,0 +1,49 @@ |
||||
// SPDX-License-Identifier: MIT OR Apache-2.0 |
||||
pragma solidity >=0.6.11; |
||||
|
||||
// ============ External Imports ============ |
||||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; |
||||
|
||||
/** |
||||
* @title InterchainGasPaymaster |
||||
* @notice Manages payments on a source chain to cover gas costs of proving |
||||
* & processing messages on destination chains. |
||||
* @dev This contract is only intended for paying for messages sent via a specific |
||||
* Outbox contract on the same source chain. |
||||
*/ |
||||
contract InterchainGasPaymaster is Ownable { |
||||
// ============ Events ============ |
||||
|
||||
/** |
||||
* @notice Emitted when a payment is made for a message's gas costs. |
||||
* @param leafIndex The index of the message in the Outbox merkle tree. |
||||
* @param amount The amount of native tokens paid. |
||||
*/ |
||||
event GasPayment(uint256 indexed leafIndex, uint256 amount); |
||||
|
||||
// ============ Constructor ============ |
||||
|
||||
// solhint-disable-next-line no-empty-blocks |
||||
constructor() Ownable() {} |
||||
|
||||
// ============ External Functions ============ |
||||
|
||||
/** |
||||
* @notice Deposits the msg.value as a payment for the proving & processing |
||||
* of a message on its destination chain. |
||||
* @param _leafIndex The index of the message in the Outbox merkle tree. |
||||
*/ |
||||
function payGasFor(uint256 _leafIndex) external payable { |
||||
emit GasPayment(_leafIndex, msg.value); |
||||
} |
||||
|
||||
/** |
||||
* @notice Transfers the entire native token balance to the owner of the contract. |
||||
* @dev The owner must be able to receive native tokens. |
||||
*/ |
||||
function claim() external { |
||||
// Transfer the entire balance to owner. |
||||
(bool success, ) = owner().call{value: address(this).balance}(""); |
||||
require(success, "!transfer"); |
||||
} |
||||
} |
@ -0,0 +1,76 @@ |
||||
import { ethers } from 'hardhat'; |
||||
import { expect } from 'chai'; |
||||
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; |
||||
|
||||
import { |
||||
InterchainGasPaymaster, |
||||
InterchainGasPaymaster__factory, |
||||
} from '../types'; |
||||
|
||||
const LEAF_INDEX = 4321; |
||||
const PAYMENT_AMOUNT = 123456789; |
||||
const OWNER = '0xdeadbeef00000000000000000000000000000000'; |
||||
|
||||
describe('InterchainGasPaymaster', async () => { |
||||
let paymaster: InterchainGasPaymaster, signer: SignerWithAddress; |
||||
|
||||
before(async () => { |
||||
[signer] = await ethers.getSigners(); |
||||
}); |
||||
|
||||
beforeEach(async () => { |
||||
const paymasterFactory = new InterchainGasPaymaster__factory(signer); |
||||
paymaster = await paymasterFactory.deploy(); |
||||
}); |
||||
|
||||
describe('#payGasFor', async () => { |
||||
it('deposits the value into the contract', async () => { |
||||
const paymasterBalanceBefore = await signer.provider!.getBalance( |
||||
paymaster.address, |
||||
); |
||||
|
||||
await paymaster.payGasFor(LEAF_INDEX, { value: PAYMENT_AMOUNT }); |
||||
|
||||
const paymasterBalanceAfter = await signer.provider!.getBalance( |
||||
paymaster.address, |
||||
); |
||||
|
||||
expect(paymasterBalanceAfter.sub(paymasterBalanceBefore)).equals( |
||||
PAYMENT_AMOUNT, |
||||
); |
||||
}); |
||||
|
||||
it('emits the GasPayment event', async () => { |
||||
await expect(paymaster.payGasFor(LEAF_INDEX, { value: PAYMENT_AMOUNT })) |
||||
.to.emit(paymaster, 'GasPayment') |
||||
.withArgs(LEAF_INDEX, PAYMENT_AMOUNT); |
||||
}); |
||||
}); |
||||
|
||||
describe('#claim', async () => { |
||||
it('sends the entire balance of the contract to the owner', async () => { |
||||
// First pay some ether into the contract
|
||||
await paymaster.payGasFor(LEAF_INDEX, { value: PAYMENT_AMOUNT }); |
||||
|
||||
// Set the owner to a different address so we aren't paying gas with the same
|
||||
// address we want to observe the balance of
|
||||
await paymaster.transferOwnership(OWNER); |
||||
|
||||
const ownerBalanceBefore = await signer.provider!.getBalance(OWNER); |
||||
expect(ownerBalanceBefore).equals(0); |
||||
const paymasterBalanceBefore = await signer.provider!.getBalance( |
||||
paymaster.address, |
||||
); |
||||
expect(paymasterBalanceBefore).equals(PAYMENT_AMOUNT); |
||||
|
||||
await paymaster.claim(); |
||||
|
||||
const ownerBalanceAfter = await signer.provider!.getBalance(OWNER); |
||||
expect(ownerBalanceAfter).equals(PAYMENT_AMOUNT); |
||||
const paymasterBalanceAfter = await signer.provider!.getBalance( |
||||
paymaster.address, |
||||
); |
||||
expect(paymasterBalanceAfter).equals(0); |
||||
}); |
||||
}); |
||||
}); |
Loading…
Reference in new issue