Commit cf796c84 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into jg/batch_decoder_reassemble_channels

parents 881d98cc 6e32eeeb
......@@ -16,9 +16,9 @@
# atst
atst is a typescript sdk and cli around the attestation station
atst is a typescript / javascript sdk and cli around AttestationStation
### Visit [Docs](https://community.optimism.io/docs/governance/attestation-station/) for general documentation on the attestation station!
**Visit [Docs](https://community.optimism.io/docs/governance/attestation-station/) for general documentation on AttestationStation.**
## Getting started
......@@ -28,42 +28,50 @@ Install
npm install @eth-optimism/atst wagmi @wagmi/core ethers@5.7.0
```
## atst typescript sdk
## atst typescript/javascript sdk
The typescript sdk provides a clean [wagmi](https://wagmi.sh/) based interface for reading and writing to the attestation station
The typescript sdk provides a clean [wagmi](https://wagmi.sh/) based interface for reading and writing to AttestationStation.
### See [sdk docs](https://github.com/ethereum-optimism/optimism/blob/develop/packages/atst/docs/sdk.md) for usage instructions
**See [sdk docs](https://github.com/ethereum-optimism/optimism/blob/develop/packages/atst/docs/sdk.md) for usage instructions.**
## atst cli
The cli provides a convenient cli for interacting with the attestation station contract
The cli provides a convenient cli for interacting with the AttestationStation contract
![preview](./assets/preview.gif)
## React API
**See [cli docs](https://github.com/ethereum-optimism/optimism/blob/develop/packages/atst/docs/cli.md) for usage instructions.**
For react hooks we recomend using the [wagmi cli](https://wagmi.sh/cli/getting-started) with the [etherscan plugin](https://wagmi.sh/cli/plugins/etherscan) and [react plugin](https://wagmi.sh/cli/plugins/react) to automatically generate react hooks around the attestation station.
## React API
Use `createKey` and `createValue` to convert your raw keys and values into bytes that can be used in the attestation station contract calls
For react hooks we recomend using the [wagmi cli](https://wagmi.sh/cli/getting-started) with the [etherscan plugin](https://wagmi.sh/cli/plugins/etherscan) and [react plugin](https://wagmi.sh/cli/plugins/react) to automatically generate react hooks around AttestationStation.
Use `parseString`, `parseBool`, `parseAddress` and `parseNumber` to convert values returned by attestation station to their correct data type.
Use `createKey` and `createValue` to convert your raw keys and values into bytes that can be used in AttestationStation contract calls
For convenience we also export the hooks here.
Use `parseString`, `parseBool`, `parseAddress` and `parseNumber` to convert values returned by AttestationStation to their correct data type.
`useAttestationStationAttestation` - Reads attestations with useContractRead
For convenience we also [export the hooks here](https://github.com/ethereum-optimism/optimism/blob/develop/packages/atst/src/index.ts):
- `useAttestationStationAttestation` - Reads attestations with useContractRead
- `useAttestationStationVersion` - Reads attestation version
- `useAttestationStationAttest` - Wraps useContractWrite with AttestationStation abi calling attest
- `usePrepareAttestationStationAttest` - Wraps usePrepare with AttestationStation abi calling attest
- `useAttestationStationAttestationCreatedEvent` - Wraps useContractEvents for Created events
`useAttestationStationVersion` - Reads attestation version
Also some more hooks exported by the cli but these are likely the only ones you need.
`useAttestationStationAttest` - Wraps useContractWrite with attestation station abi calling attest
## Contributing
`usePrepareAttestationStationAttest` - Wraps usePrepare with attestation station abi calling attest
Please see our [contributing.md](https://github.com/ethereum-optimism/optimism/blob/develop/CONTRIBUTING.md). No contribution is too small.
`useAttestationStationAttestationCreatedEvent` - Wraps useContractEvents for Created events
Having your contribution denied feels bad.
Please consider [opening an issue](https://github.com/ethereum-optimism/optimism/issues) before adding any new features or apis.
Also some more hooks exported by the cli but these are likely the only ones you need.
## Contributing
## Getting help
Please see our [contributing.md](docs/contributing.md). No contribution is too small.
If you have any problems, these resources could help you:
Having your contribution denied feels bad. Please consider opening an issue before adding any new features or apis
- [sdk documentation](https://github.com/ethereum-optimism/optimism/blob/develop/packages/atst/docs/sdk.md)
- [cli documentation](https://github.com/ethereum-optimism/optimism/blob/develop/packages/atst/docs/cli.md)
- [Optimism Discord](https://discord-gateway.optimism.io/)
- [Telegram group](https://t.me/+zwpJ8Ohqgl8yNjNh)
......@@ -63,9 +63,9 @@ npx atst read --key "optimist.base-uri" --about 0x2335022c740d17c2837f9C884Bfe4f
Example:
```bash
atst write --key "optimist.base-uri" \
npx atst write --key "optimist.base-uri" \
--about 0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5 \
--value "my attestation" \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--rpc-url http://localhost:8545
--rpc-url http://goerli.optimism.io
```
# atst sdk docs
# AttestationStation sdk docs
Typescript sdk for interacting with the ATST based on [@wagmi/core](https://wagmi.sh/core/getting-started)
......@@ -150,7 +150,7 @@ const attestation = await readAttestation(
about, // Address: The about topic of the attestation
key, // string: The key of the attestation
dataType, // Optional, the data type of the attestation, 'string' | 'bytes' | 'number' | 'bool' | 'address'
contractAddress // Optional address: the contract address of the attestation station
contractAddress // Optional address: the contract address of AttestationStation
)
```
......@@ -193,7 +193,7 @@ These definitions allow you to communicate with AttestationStation, but are not
#### `ATTESTATION_STATION_ADDRESS`
The deployment address for the attestation station currently deployed with create2 on Optimism and Optimism Goerli `0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77`.
The deployment address for AttestationStation currently deployed with create2 on Optimism and Optimism Goerli `0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77`.
```typescript
import { ATTESTATION_STATION_ADDRESS } from '@eth-optimism/atst'
......@@ -201,7 +201,7 @@ import { ATTESTATION_STATION_ADDRESS } from '@eth-optimism/atst'
#### `abi`
The abi of the attestation station contract
The abi of the AttestationStation contract
```typescript
import { abi } from '@eth-optimism/atst'
......@@ -265,24 +265,26 @@ const bigNumberAttestation = stringifyAttestationBytes(
)
```
**Note:** `writeAttestation` already does this for you so this is only needed if using a library other than the attestation station.
**Note:** `writeAttestation` already does this for you so this is only needed if using a library other than `atst`.
### React API
For react hooks we recomend using the [wagmi cli](https://wagmi.sh/cli/getting-started) with the [etherscan plugin](https://wagmi.sh/cli/plugins/etherscan) and [react plugin](https://wagmi.sh/cli/plugins/react) to automatically generate react hooks around the attestation station.
For react hooks we recomend using the [wagmi cli](https://wagmi.sh/cli/getting-started) with the [etherscan plugin](https://wagmi.sh/cli/plugins/etherscan) and [react plugin](https://wagmi.sh/cli/plugins/react) to automatically generate react hooks around AttestationStation.
Use `createKey` and `createValue` to convert your raw keys and values into bytes that can be used in the attestation station contract calls.
Use `parseString`, `parseBool`, `parseAddress` and `parseNumber` to convert values returned by attestation station to their correct data type.
Use `createKey` and `createValue` to convert your raw keys and values into bytes that can be used in AttestationStation contract calls.
Use `parseString`, `parseBool`, `parseAddress` and `parseNumber` to convert values returned by AttestationStation to their correct data type.
For convenience we also [export the hooks](../src/react.ts) here:
For convenience we also [export the hooks here](../src/react.ts):
- `useAttestationStationAttestation` - Reads attestations with useContractRead
- `useAttestationStationVersion` - Reads attestation version
- `useAttestationStationAttest` - Wraps useContractWrite with attestation station abi calling attest
- `usePrepareAttestationStationAttest` - Wraps usePrepare with attestation station abi calling attest
- `useAttestationStationAttest` - Wraps useContractWrite with AttestationStation abi calling attest
- `usePrepareAttestationStationAttest` - Wraps usePrepare with AttestationStation abi calling attest
- `useAttestationStationAttestationCreatedEvent` - Wraps useContractEvents for Created events
## Tutorial
For a tutorial on using the attestation station in general, see out tutorial as well as other Optimism related tutorials in our [optimism-tutorial](https://github.com/ethereum-optimism/optimism-tutorial/tree/main/ecosystem/attestation-station#key-values) repo.
- [General atst tutorial](https://github.com/ethereum-optimism/optimism-tutorial/tree/main/ecosystem/attestation-station).
- [React atst starter](https://github.com/ethereum-optimism/optimism-starter).
......@@ -59,5 +59,15 @@
"@wagmi/core": "^0.9.2",
"@wagmi/cli": "~0.1.5",
"wagmi": "~0.11.0"
}
},
"keywords": [
"react",
"hooks",
"eth",
"ethereum",
"dapps",
"web3",
"optimism",
"attestation"
]
}
This diff is collapsed.
......@@ -8,27 +8,22 @@ import "./CommonTest.t.sol";
import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol";
import { ResourceMetering } from "../L1/ResourceMetering.sol";
uint128 constant INITIAL_BASE_FEE = 1_000_000_000;
// Free function for setting the prevBaseFee param in the OptimismPortal.
function setPrevBaseFee(
Vm _vm,
address _op,
uint128 _prevBaseFee
) {
_vm.store(
address(_op),
bytes32(uint256(1)),
bytes32(
abi.encode(
ResourceMetering.ResourceParams({
prevBaseFee: _prevBaseFee,
prevBoughtGas: 0,
prevBlockNum: uint64(block.number)
})
)
)
);
_vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee));
}
contract SetPrevBaseFee_Test is Portal_Initializer {
function test_setPrevBaseFee_succeeds() external {
setPrevBaseFee(vm, address(op), 100 gwei);
(uint128 prevBaseFee, , uint64 prevBlockNum) = op.params();
assertEq(uint256(prevBaseFee), 100 gwei);
assertEq(uint256(prevBlockNum), block.number);
}
}
// Tests for obtaining pure gas cost estimates for commonly used functions.
......@@ -37,6 +32,8 @@ function setPrevBaseFee(
// In order to achieve this we make no assertions, and handle everything else in the setUp()
// function.
contract GasBenchMark_OptimismPortal is Portal_Initializer {
uint128 INITIAL_BASE_FEE;
// Reusable default values for a test withdrawal
Types.WithdrawalTransaction _defaultTx;
......@@ -76,7 +73,7 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
}
// Get the system into a nice ready-to-use state.
function setUp() public override {
function setUp() public virtual override {
// Configure the oracle to return the output root we've prepared.
vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(oracle.PROPOSER());
......@@ -88,6 +85,9 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
oracle.FINALIZATION_PERIOD_SECONDS() +
1
);
INITIAL_BASE_FEE = op.INITIAL_BASE_FEE();
// Fund the portal so that we can withdraw ETH.
vm.deal(address(op), 0xFFFFFFFF);
}
......@@ -124,45 +124,83 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
}
contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {
uint128 INITIAL_BASE_FEE;
function setUp() public virtual override {
super.setUp();
INITIAL_BASE_FEE = op.INITIAL_BASE_FEE();
}
function test_sendMessage_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
// The amount of data typically sent during a bridge deposit.
bytes
memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
vm.resumeGasMetering();
L1Messenger.sendMessage(bob, data, uint32(100));
}
function test_sendMessage_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
// The amount of data typically sent during a bridge deposit.
bytes
memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
vm.resumeGasMetering();
L1Messenger.sendMessage(bob, data, uint32(100));
}
}
contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
uint128 INITIAL_BASE_FEE;
function setUp() public virtual override {
super.setUp();
INITIAL_BASE_FEE = op.INITIAL_BASE_FEE();
deal(address(L1Token), alice, 100000, true);
vm.startPrank(alice, alice);
L1Token.approve(address(L1Bridge), type(uint256).max);
}
function test_depositETH_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
vm.resumeGasMetering();
L1Bridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositETH_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
vm.resumeGasMetering();
L1Bridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositERC20_benchmark_0() external {
L1Bridge.depositETH{ value: 500 }(50000, hex"");
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
vm.resumeGasMetering();
L1Bridge.bridgeERC20({
_localToken: address(L1Token),
_remoteToken: address(L2Token),
_amount: 100,
_minGasLimit: 100_000,
_extraData: hex""
});
}
function test_depositERC20_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
L1Bridge.depositETH{ value: 500 }(50000, hex"");
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
vm.resumeGasMetering();
L1Bridge.bridgeERC20({
_localToken: address(L1Token),
_remoteToken: address(L2Token),
_amount: 100,
_minGasLimit: 100_000,
_extraData: hex""
});
}
}
......
......@@ -156,8 +156,8 @@ contract L2OutputOracle_Initializer is CommonTest {
contract Portal_Initializer is L2OutputOracle_Initializer {
// Test target
OptimismPortal opImpl;
OptimismPortal op;
OptimismPortal internal opImpl;
OptimismPortal internal op;
event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);
event WithdrawalProven(
......@@ -177,14 +177,14 @@ contract Portal_Initializer is L2OutputOracle_Initializer {
abi.encodeWithSelector(OptimismPortal.initialize.selector, false)
);
op = OptimismPortal(payable(address(proxy)));
vm.label(address(op), "OptimismPortal");
}
}
contract Messenger_Initializer is L2OutputOracle_Initializer {
OptimismPortal op;
AddressManager addressManager;
L1CrossDomainMessenger L1Messenger;
L2CrossDomainMessenger L2Messenger =
contract Messenger_Initializer is Portal_Initializer {
AddressManager internal addressManager;
L1CrossDomainMessenger internal L1Messenger;
L2CrossDomainMessenger internal L2Messenger =
L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);
event SentMessage(
......@@ -220,17 +220,11 @@ contract Messenger_Initializer is L2OutputOracle_Initializer {
bytes data
);
event WithdrawalFinalized(bytes32 indexed, bool success);
event WhatHappened(bool success, bytes returndata);
function setUp() public virtual override {
super.setUp();
// Deploy the OptimismPortal
op = new OptimismPortal({ _l2Oracle: oracle, _guardian: guardian, _paused: false });
vm.label(address(op), "OptimismPortal");
// Deploy the address manager
vm.prank(multisig);
addressManager = new AddressManager();
......
......@@ -41,7 +41,7 @@ contract StandardBridgeTester is StandardBridge {
contract LegacyMintable is ERC20, ILegacyMintableERC20 {
constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}
function l1Token() external view returns (address) {
function l1Token() external pure returns (address) {
return address(0);
}
......@@ -55,7 +55,7 @@ contract LegacyMintable is ERC20, ILegacyMintableERC20 {
* check. Allows for testing against code that is has been deployed,
* assuming different compiler version is no problem.
*/
function supportsInterface(bytes4 _interfaceId) external view returns (bool) {
function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {
bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165
bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^
ILegacyMintableERC20.mint.selector ^
......
......@@ -141,16 +141,6 @@ abstract contract CrossDomainMessenger is
*/
uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;
/**
* @notice Minimum amount of gas required to relay a message.
*/
uint256 internal constant RELAY_GAS_REQUIRED = 45_000;
/**
* @notice Amount of gas held in reserve to guarantee that relay execution completes.
*/
uint256 internal constant RELAY_GAS_BUFFER = RELAY_GAS_REQUIRED - 5000;
/**
* @notice Address of the paired CrossDomainMessenger contract on the other chain.
*/
......@@ -367,16 +357,11 @@ abstract contract CrossDomainMessenger is
"CrossDomainMessenger: message has already been relayed"
);
require(
gasleft() >= _minGasLimit + RELAY_GAS_REQUIRED,
"CrossDomainMessenger: insufficient gas to relay message"
);
xDomainMsgSender = _sender;
bool success = SafeCall.call(_target, gasleft() - RELAY_GAS_BUFFER, _value, _message);
bool success = SafeCall.callWithMinGas(_target, _minGasLimit, _value, _message);
xDomainMsgSender = Constants.DEFAULT_L2_SENDER;
if (success == true) {
if (success) {
successfulMessages[versionedHash] = true;
emit RelayedMessage(versionedHash);
} else {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment