Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
114098b
feat(validation): require a minimum refund window between the expiries
pviti Jul 29, 2026
b331fdb
perf(build): raise optimizer_runs to 10_000
pviti Jul 30, 2026
cc0cbfb
Merge pull request #53 from commercelayer/feature/minimum-refund-window
pviti Jul 31, 2026
14e4469
fix(eip3009): authorize/charge pull funds via receiveWithAuthorization
pviti Jul 30, 2026
793296d
fix(refund): derive the nonce from both balances so it can never repeat
pviti Jul 30, 2026
dce196c
docs: carry the new refundNonce arity into every place it is published
pviti Aug 18, 2026
b4b6c6a
perf(gas): transient reentrancy lock and one fewer configHash SLOAD
pviti Jul 29, 2026
afef724
chore(solc): move to 0.8.31 and express the lock with `transient`
pviti Jul 29, 2026
c0a56fe
chore(solc): state ^0.8.31 on every pragma
pviti Jul 29, 2026
ca72f68
chore(solc): bump the deploy script's pragma too
pviti Jul 29, 2026
44958c8
chore(interfaces): raise IEIP3009 to the same pragma as the rest
pviti Aug 18, 2026
6fe7774
Merge remote-tracking branch 'origin/perf/gas-transient-lock-and-slot…
pviti Aug 18, 2026
d2dbc45
Merge remote-tracking branch 'origin/fix/authorize-charge-front-runni…
pviti Aug 18, 2026
24e5989
chore(release): VERSION 1.4.0
pviti Aug 18, 2026
13fb526
Merge remote-tracking branch 'origin/v1.4.0' into v1.4.0
pviti Aug 18, 2026
b1e8b9e
fix(test): point #53's new tests at the receive-typehash signer
pviti Aug 18, 2026
99ed4ae
docs: carry the refundNonce arity into the two places it was still wrong
pviti Aug 19, 2026
838a5d6
chore(build): point foundry.toml at the deployment set, pin the pragma
pviti Aug 19, 2026
2229de3
chore(editor): point the editor at the same solc the project builds with
pviti Aug 19, 2026
f6040f7
Merge pull request #65 from commercelayer/fix/issue-36-43-docs-and-bu…
pviti Aug 24, 2026
7013cdf
docs: name the variant the code actually calls — Receive, not Transfer
pviti Aug 25, 2026
0610975
Merge pull request #74 from commercelayer/docs/receive-authorization-…
pviti Aug 25, 2026
afce2f4
Merge pull request #59 from commercelayer/perf/optimizer-runs
pviti Aug 25, 2026
f437289
docs(site): carry the 1.4.0 facts the release changes
pviti Aug 25, 2026
d5eb075
Merge pull request #76 from commercelayer/fix/release-1.4.0-site-and-…
pviti Aug 25, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

# solc is pinned in foundry.toml (0.8.27), so this compiles with the same
# solc is pinned in foundry.toml (0.8.31), so this compiles with the same
# compiler the deployments used rather than whatever ships with the toolchain.
- name: Format
run: forge fmt --check
Expand Down
35 changes: 35 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
// Pin the editor to the SAME compiler the project builds with.
//
// contracts/foundry.toml pins `solc = "0.8.31"` and forge fetches it, so the
// command line has always been correct. An editor extension, though, uses the
// compiler it ships with — and while the pragma was `^0.8.31` it happily
// compiled these files with whatever newer 0.8.x that happened to be, producing
// different bytecode than the deployed artifact and saying nothing about it.
// That silent divergence is what issue #43 was about.
//
// With the pragma now `=0.8.31`, a mismatched extension reports:
//
// Source file requires different compiler version (current compiler is
// 0.8.36+commit.8a079791.Emscripten.clang)
//
// which is the pin working, not a fault. The fix is to point the editor at
// 0.8.31 rather than to install something newer — newer is the problem.
//
// Both keys are here because the two common extensions read different ones;
// whichever you don't have simply ignores its key. The exact build is the one
// forge used, read back from the compiled artifact's metadata rather than
// typed from memory.

// Juan Blanco's `solidity` extension.
"solidity.compileUsingRemoteVersion": "v0.8.31+commit.fd3a2265",

// Nomic Foundation's `hardhat-solidity` / Solidity extension.
"solidity.compilerVersion": "0.8.31",

// Foundry formats this repo (`forge fmt`), so the editor must not reformat
// Solidity on save with its own rules — that fights `forge fmt --check` in CI.
"[solidity]": {
"editor.formatOnSave": false
}
}
51 changes: 30 additions & 21 deletions README.md

Large diffs are not rendered by default.

46 changes: 36 additions & 10 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@ src = "src"
out = "out"
libs = ["lib"]
test = "test"
solc = "0.8.27"
solc = "0.8.31"
optimizer = true
optimizer_runs = 200
# 10_000, not the 200 default: this contract deploys once per chain and is then
# called for the life of the deployment, so the trade is one-time deploy gas
# (~+550k) and bytecode size (8.0k -> 10.7k, ample headroom under the 24,576
# limit) for a measured ~360-640 gas saved on EVERY operation (capture, refund,
# authorize, ...). Bytecode differs from the v1.x deployments (200 runs) --
# verification metadata must use this value from v2.0.0 onward.
optimizer_runs = 10_000
via_ir = true
# Pinned rather than inherited from forge's default (today "prague"): the contract
# depends on Cancun for MCOPY and, since #45, for TSTORE/TLOAD. Naming the oldest
# fork that satisfies it keeps the bytecode deployable on every Cancun chain and stops
# a future forge default from silently raising the requirement.
evm_version = "cancun"
verbosity = 2
fs_permissions = [{ access = "read", path = "./" }]

Expand All @@ -21,14 +32,29 @@ bracket_spacing = true
# inline assembly hurts readability — not worth the trade.
exclude_lints = ["asm-keccak256"]

# The DEPLOYMENT SET, and only it. Every chain the README lists as Live gets an RPC
# and a verifier here, so a redeploy or a verification runs from this file instead of
# out-of-band URLs. Chains that do not run RAIL0 are deliberately absent — listing
# them advertised support that does not exist: Tempo cannot run it at all (TIP-20 has
# no EIP-3009), Plasma's testnet is still Planned, and Moderato appeared nowhere in
# the README. Every chain id below was checked against its endpoint's eth_chainId.
[rpc_endpoints]
moderato = "https://rpc.moderato.tempo.xyz"
tempo = "https://rpc.tempo.xyz"
arc-testnet = "https://rpc.testnet.arc.network"
plasma-testnet = "https://testnet-rpc.plasma.to"
celo-sepolia = "https://forno.celo-sepolia.celo-testnet.org"
arbitrum-sepolia = "https://sepolia-rollup.arbitrum.io/rpc"
arc-testnet = "https://rpc.testnet.arc.network"
base-sepolia = "https://sepolia.base.org"
celo-sepolia = "https://forno.celo-sepolia.celo-testnet.org"
optimism-sepolia = "https://sepolia.optimism.io"
polygon-amoy = "https://polygon-amoy.drpc.org"

# Five of the six explorers are Blockscout, which verifies with no API key — the
# `/api/` suffix is the verifier endpoint, not the browse URL, and each was confirmed
# to answer. Polygon Amoy is the exception and the reason `key` is not simply "" for
# every row: Polygonscan's V1 API is retired, so Amoy goes through Etherscan's V2
# endpoint, the only entry here that needs a key.
[etherscan]
tempo = { url = "https://contracts.tempo.xyz", chain = 4217, key = "" }
moderato = { url = "https://contracts.tempo.xyz", chain = 42431, key = "" }
celo-sepolia = { url = "https://celo-sepolia.blockscout.com/api/", chain = 11142220, key = "" }
arbitrum-sepolia = { url = "https://arbitrum-sepolia.blockscout.com/api/", chain = 421614, key = "" }
arc-testnet = { url = "https://testnet.arcscan.app/api/", chain = 5042002, key = "" }
base-sepolia = { url = "https://base-sepolia.blockscout.com/api/", chain = 84532, key = "" }
celo-sepolia = { url = "https://celo-sepolia.blockscout.com/api/", chain = 11142220, key = "" }
optimism-sepolia = { url = "https://testnet-explorer.optimism.io/api/", chain = 11155420, key = "" }
polygon-amoy = { url = "https://api.etherscan.io/v2/api", chain = 80002, key = "${ETHERSCAN_API_KEY}" }
2 changes: 1 addition & 1 deletion contracts/script/Deploy.s.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
pragma solidity =0.8.31;

import { Script, console2 } from "forge-std/Script.sol";
import { RAIL0 } from "../src/RAIL0.sol";
Expand Down
Loading
Loading