Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
32 changes: 19 additions & 13 deletions .treb/addressbook.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,6 @@
"TransparentUpgradeableProxy:Locking": "0x001Bb66636dCd149A1A2bA8C50E408BdDd80279C",
"L2SequencerUptimeFeed": "0x4CD491Dc27C8B0BbD10D516A502856B786939d18"
},
"143": {
"AUSD": "0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a",
"USDC": "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
"USDT0": "0xe7cd86e13ac4309349f30b3435a9d337750fc82d",
"StableTokenSpokeUSD": "0x866a7e4611C127DCe1a14C6841D2eA962A68dc88",
"StableTokenSpokeGBP": "0xddF082068Caa5B941ED8c603ADf0cecBdBb59f8E",
"StableTokenSpokeImplementation": "0xa8caCd5d58F98Ee303fb54EF101AA4e277777E91",
"MigrationMultisig": "0x58099B74F4ACd642Da77b4B7966b4138ec5Ba458",
"ProtocolFeeRecipient": "0x0Dd57F6f181D0469143fe9380762d8a112e96e4a",
"FeeSetter": "0x58099B74F4ACd642Da77b4B7966b4138ec5Ba458",
"ReserveSafe": "0x87647780180B8f55980C7D3fFeFe08a9B29e9aE1",
"WormholeCoreBridge": "0x194B123c5E96B9b2E49763619985790Dc241CAC0"
},
"11142220": {
"MigrationMultisig": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
"ReserveSafe": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
Expand All @@ -84,6 +71,19 @@
"L2SequencerUptimeFeed": "0x0000000000000000000000000000000000000000",
"BiPoolManagerFeeSetter": "0x15b38D560928029a74d1D0a56eE232fb5Ff3A4B1"
},
"143": {
"AUSD": "0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a",
"USDC": "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
"USDT0": "0xe7cd86e13ac4309349f30b3435a9d337750fc82d",
"StableTokenSpokeUSD": "0x866a7e4611C127DCe1a14C6841D2eA962A68dc88",
"StableTokenSpokeGBP": "0xddF082068Caa5B941ED8c603ADf0cecBdBb59f8E",
"StableTokenSpokeImplementation": "0xa8caCd5d58F98Ee303fb54EF101AA4e277777E91",
"MigrationMultisig": "0x58099B74F4ACd642Da77b4B7966b4138ec5Ba458",
"ProtocolFeeRecipient": "0x0Dd57F6f181D0469143fe9380762d8a112e96e4a",
"FeeSetter": "0x58099B74F4ACd642Da77b4B7966b4138ec5Ba458",
"ReserveSafe": "0x87647780180B8f55980C7D3fFeFe08a9B29e9aE1",
"WormholeCoreBridge": "0x194B123c5E96B9b2E49763619985790Dc241CAC0"
},
"10143": {
"USDC": "0x534b2f3a21130d7a60830c2df862319e593943a3",
"MigrationMultisig": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
Expand All @@ -93,12 +93,18 @@
"Watchdog": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
"YieldSplitAddress": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7"
},
"137": {
"WormholeCoreBridge": "0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7"
},
"80002": {
"MigrationMultisig": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
"ReserveSafe": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
"ProtocolFeeRecipient": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
"FeeSetter": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7"
},
"8453": {
"WormholeCoreBridge": "0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6"
},
"84532": {
"MigrationMultisig": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
"ReserveSafe": "0x2738F38Fde510743e0c589415E0598C4ceE6eAa7",
Expand Down
2 changes: 1 addition & 1 deletion .trunk/trunk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ runtimes:
# This is the section where you manage your linters. (https://docs.trunk.io/check/configuration)
lint:
ignore:
- linters: [gitleaks, trufflehog]
- linters: [gitleaks, trufflehog, checkov]
paths:
- .treb/*.json # Blockchain contract addresses, not secrets
- broadcast/**/*.json # Forge deployment transaction logs
Expand Down
43 changes: 37 additions & 6 deletions script/config/wormhole/NTTConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ library NTTConfig {
uint16 internal constant CELO_WH_CHAIN_ID = 14;
uint256 internal constant MONAD_EVM_CHAIN_ID = 143;
uint16 internal constant MONAD_WH_CHAIN_ID = 48;
uint256 internal constant POLYGON_EVM_CHAIN_ID = 137;
uint16 internal constant POLYGON_WH_CHAIN_ID = 5;
uint256 internal constant BASE_EVM_CHAIN_ID = 8453;
uint16 internal constant BASE_WH_CHAIN_ID = 30;

// ── Rate limit constants ────────────────────────────────────────────
uint256 internal constant USDm_RATE_LIMIT = 500_000e18;
Expand All @@ -50,13 +54,13 @@ library NTTConfig {
// ── Token config getters ─────────────────────────────────────────────

/// @notice Returns the full NTT bridge topology for USDm.
/// USDm is burn-mint on BOTH Celo and Monad.
/// USDm is burn-mint on Celo, Monad, and Polygon.
function getUSDmConfig() internal pure returns (NTTTokenConfig memory config) {
config.tokenName = "USDm";
config.tokenDecimals = 18;
config.ownerLabel = "migrationOwner";

config.chains = new NTTChainConfig[](2);
config.chains = new NTTChainConfig[](3);
config.chains[0] = NTTChainConfig({
chainName: "celo",
evmChainId: CELO_EVM_CHAIN_ID,
Expand All @@ -73,10 +77,19 @@ library NTTConfig {
isBurning: true,
outboundLimit: USDm_RATE_LIMIT
});
config.chains[2] = NTTChainConfig({
chainName: "polygon",
evmChainId: POLYGON_EVM_CHAIN_ID,
wormholeChainId: POLYGON_WH_CHAIN_ID,
tokenLabel: "USDm",
isBurning: true,
outboundLimit: USDm_RATE_LIMIT
});

config.inboundLimits = new NTTInboundLimit[](2);
config.inboundLimits = new NTTInboundLimit[](3);
config.inboundLimits[0] = NTTInboundLimit({fromChainName: "monad", limit: USDm_RATE_LIMIT});
config.inboundLimits[1] = NTTInboundLimit({fromChainName: "celo", limit: USDm_RATE_LIMIT});
config.inboundLimits[2] = NTTInboundLimit({fromChainName: "polygon", limit: USDm_RATE_LIMIT});
Comment thread
nvtaveras marked this conversation as resolved.
}

/// @notice Returns the full NTT bridge topology for GBPm.
Expand Down Expand Up @@ -110,13 +123,13 @@ library NTTConfig {
}

/// @notice Returns the full NTT bridge topology for EURm.
/// EURm is burn-mint on BOTH Celo and Monad.
/// EURm is burn-mint on Celo, Monad, Polygon, and Base.
function getEURmConfig() internal pure returns (NTTTokenConfig memory config) {
config.tokenName = "EURm";
config.tokenDecimals = 18;
config.ownerLabel = "migrationOwner";

config.chains = new NTTChainConfig[](2);
config.chains = new NTTChainConfig[](4);
config.chains[0] = NTTChainConfig({
chainName: "celo",
evmChainId: CELO_EVM_CHAIN_ID,
Expand All @@ -133,10 +146,28 @@ library NTTConfig {
isBurning: true,
outboundLimit: EURm_RATE_LIMIT
});
config.chains[2] = NTTChainConfig({
chainName: "polygon",
evmChainId: POLYGON_EVM_CHAIN_ID,
wormholeChainId: POLYGON_WH_CHAIN_ID,
tokenLabel: "EURm",
isBurning: true,
outboundLimit: EURm_RATE_LIMIT
});
config.chains[3] = NTTChainConfig({
chainName: "base",
evmChainId: BASE_EVM_CHAIN_ID,
wormholeChainId: BASE_WH_CHAIN_ID,
tokenLabel: "EURm",
isBurning: true,
outboundLimit: EURm_RATE_LIMIT
});

config.inboundLimits = new NTTInboundLimit[](2);
config.inboundLimits = new NTTInboundLimit[](4);
config.inboundLimits[0] = NTTInboundLimit({fromChainName: "monad", limit: EURm_RATE_LIMIT});
config.inboundLimits[1] = NTTInboundLimit({fromChainName: "celo", limit: EURm_RATE_LIMIT});
config.inboundLimits[2] = NTTInboundLimit({fromChainName: "polygon", limit: EURm_RATE_LIMIT});
config.inboundLimits[3] = NTTInboundLimit({fromChainName: "base", limit: EURm_RATE_LIMIT});
}

/// @notice Returns the full NTT bridge topology for JPYm.
Expand Down
10 changes: 4 additions & 6 deletions script/deploy/dex/DeployMockCollaterals.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@ contract DeployMockCollaterals is TrebScript {

for (uint256 i = 0; i < mocks.length; i++) {
string memory symbol = mocks[i];
uint256 decimals = config.getTokenDecimals(symbol);

address addy = deployer.create3("MockERC20").setLabel(symbol)
.deploy(
abi.encode(
string.concat("Mento Mock ", symbol), symbol, config.getTokenDecimals(symbol), deployer.account
)
);
.deploy(abi.encode(string.concat("Mento Mock ", symbol), symbol, decimals, deployer.account));

MockERC20 coll = MockERC20(deployer.harness(addy));
coll.mint(deployer.account, 1000000e18);
coll.mint(deployer.account, 1_000_000 * 10 ** decimals);
IOwnable(address(coll)).transferOwnership(address(migrationOwner.account));
console.log("Deployed MockERC20 (%s) at %s", symbol, addy);
}
Expand Down
83 changes: 62 additions & 21 deletions script/deploy/wormhole/ConfigureNTT.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ contract ConfigureNTT is NTTScriptBase {
peerInboundLimits.push(_findInboundLimit(config, peer.chainName));
}

console.log("=== ConfigureNTT: %s on %s (chain %d) ===", tokenName, _myChain.chainName, _myChain.evmChainId);
console.log("");
console.log("============================================================");
console.log(" ConfigureNTT: %s on %s (chain %d)", tokenName, _myChain.chainName, _myChain.evmChainId);
console.log("============================================================");
console.log(" NttManager: %s", localNttManager);
console.log(" Transceiver: %s", localTransceiver);
console.log(" Mode: %s", _myChain.isBurning ? "burning" : "locking");
Expand Down Expand Up @@ -123,7 +126,9 @@ contract ConfigureNTT is NTTScriptBase {
_setupOwnership(migrationOwner);

console.log("");
console.log("=== ConfigureNTT: %s complete ===", tokenName);
console.log("============================================================");
console.log(" ConfigureNTT: %s on %s complete", tokenName, myChain.chainName);
console.log("============================================================");
}

// ── Setup helpers (idempotent) ──────────────────────────────────────
Expand All @@ -134,91 +139,127 @@ contract ConfigureNTT is NTTScriptBase {
address remoteXceiver = remoteTransceivers[peerIdx];
uint256 inboundLimit = peerInboundLimits[peerIdx];

console.log(" Peer: %s (wormhole chain %d)", peer.chainName, uint256(peer.wormholeChainId));
console.log("");
console.log(" ------------------------------------------------------------");
console.log(" >> Peer #%d: %s -> %s", peerIdx + 1, myChain.chainName, peer.chainName);
console.log(" ------------------------------------------------------------");
console.log(" Remote chain: %s (wormhole id %d)", peer.chainName, uint256(peer.wormholeChainId));
console.log(" Remote NttManager: %s", remoteManager);
console.log(" Remote Transceiver: %s", remoteXceiver);
console.log(" Inbound limit: %d %s", inboundLimit / 1e18, tokenName);
console.log("");

// NTT Manager peer
bytes32 expectedPeerManager = _toBytes32(remoteManager);
NttManagerPeer memory existingPeer = INTTManager(localNttManager).getPeer(peer.wormholeChainId);

if (existingPeer.peerAddress != expectedPeerManager) {
console.log(" > Setting NTT Manager peer...");
console.log(" [+] NttManager (%s) -> peer %s (%s)", myChain.chainName, peer.chainName, remoteManager);
console.log(" Setting NTT Manager peer...");
INTTManager(migrationOwner.harness(localNttManager))
.setPeer(peer.wormholeChainId, expectedPeerManager, tokenDecimals, inboundLimit);
} else {
console.log(" > NTT Manager peer already set, checking inbound limit...");
console.log(" [=] NttManager (%s) -> peer %s already set, skipping", myChain.chainName, peer.chainName);
uint256 currentInbound =
_untrim(INTTManager(localNttManager).getInboundLimitParams(peer.wormholeChainId).limit);
if (currentInbound != inboundLimit) {
console.log(" > Updating inbound limit...");
console.log(
" Updating inbound limit from %d to %d %s...",
currentInbound / 1e18,
inboundLimit / 1e18,
tokenName
);
INTTManager(migrationOwner.harness(localNttManager)).setInboundLimit(inboundLimit, peer.wormholeChainId);
} else {
console.log(" > Inbound limit already correct");
console.log(" Inbound limit already correct (%d %s), skipping", inboundLimit / 1e18, tokenName);
}
}

// Transceiver wormhole peer
bytes32 expectedPeerXceiver = _toBytes32(remoteXceiver);
if (ITransceiver(localTransceiver).getWormholePeer(peer.wormholeChainId) != expectedPeerXceiver) {
console.log(" > Setting Transceiver wormhole peer...");
console.log(" [+] Transceiver (%s) -> peer %s (%s)", myChain.chainName, peer.chainName, remoteXceiver);
console.log(" Setting Transceiver wormhole peer...");
ITransceiver(migrationOwner.harness(localTransceiver))
.setWormholePeer(peer.wormholeChainId, expectedPeerXceiver);
} else {
console.log(" > Transceiver wormhole peer already set");
console.log(" [=] Transceiver (%s) -> peer %s already set, skipping", myChain.chainName, peer.chainName);
}
}

function _setupOutboundLimit(Senders.Sender storage migrationOwner) internal {
console.log("");
console.log(" ------------------------------------------------------------");
console.log(" >> Outbound rate limit (%s)", myChain.chainName);
console.log(" ------------------------------------------------------------");
uint256 currentOutbound = _untrim(INTTManager(localNttManager).getOutboundLimitParams().limit);
if (currentOutbound != myChain.outboundLimit) {
console.log(" > Setting outbound limit to %d...", myChain.outboundLimit / 1e18);
console.log(
" [+] Setting outbound limit: %d -> %d %s",
currentOutbound / 1e18,
myChain.outboundLimit / 1e18,
tokenName
);
INTTManager(migrationOwner.harness(localNttManager)).setOutboundLimit(myChain.outboundLimit);
} else {
console.log(" > Outbound limit already correct, skipping");
console.log(" [=] Outbound limit already %d %s, skipping", myChain.outboundLimit / 1e18, tokenName);
}
}

function _setupBurnMintPermissions(Senders.Sender storage migrationOwner) internal {
console.log("");
console.log(" ------------------------------------------------------------");
console.log(" >> Burn/Mint permissions (%s)", myChain.chainName);
console.log(" ------------------------------------------------------------");
address token = lookupProxyOrFail(myChain.tokenLabel);
console.log(" Token: %s (%s)", myChain.tokenLabel, token);
console.log(" NttManager: %s", localNttManager);
console.log("");

if (!IStableTokenSpoke(token).isBurner(localNttManager)) {
console.log(" > Granting NTT Manager burner permission...");
console.log(" [+] Granting NTT Manager burner permission on %s...", myChain.tokenLabel);
IStableTokenSpoke(migrationOwner.harness(token)).setBurner(localNttManager, true);
} else {
console.log(" > NTT Manager already has burner permission, skipping");
console.log(" [=] NTT Manager already has burner permission, skipping");
}

if (!IStableTokenSpoke(token).isMinter(localNttManager)) {
console.log(" > Granting NTT Manager minter permission...");
console.log(" [+] Granting NTT Manager minter permission on %s...", myChain.tokenLabel);
IStableTokenSpoke(migrationOwner.harness(token)).setMinter(localNttManager, true);
} else {
console.log(" > NTT Manager already has minter permission, skipping");
console.log(" [=] NTT Manager already has minter permission, skipping");
}
}

function _setupOwnership(Senders.Sender storage migrationOwner) internal {
console.log("");
console.log(" ------------------------------------------------------------");
console.log(" >> Ownership & Pauser (%s)", myChain.chainName);
console.log(" ------------------------------------------------------------");
console.log(" Target owner/pauser: %s", owner);
console.log("");

// NTT Manager ownership (cascades to all registered transceivers)
if (IOwnable(localNttManager).owner() != owner) {
console.log(" > Transferring NTT Manager ownership to %s...", owner);
console.log(" [+] Transferring NttManager ownership -> %s", owner);
IOwnable(migrationOwner.harness(localNttManager)).transferOwnership(owner);
} else {
console.log(" > NTT Manager already owned by %s, skipping", owner);
console.log(" [=] NttManager already owned by %s, skipping", owner);
}

// Pauser capability does NOT cascade — must be set on each contract
if (IPausable(localNttManager).pauser() != owner) {
console.log(" > Transferring NTT Manager pauser to %s...", owner);
console.log(" [+] Transferring NttManager pauser -> %s", owner);
IPausable(migrationOwner.harness(localNttManager)).transferPauserCapability(owner);
} else {
console.log(" > NTT Manager pauser already correct, skipping");
console.log(" [=] NttManager pauser already correct, skipping");
}

if (IPausable(localTransceiver).pauser() != owner) {
console.log(" > Transferring Transceiver pauser to %s...", owner);
console.log(" [+] Transferring Transceiver pauser -> %s", owner);
IPausable(migrationOwner.harness(localTransceiver)).transferPauserCapability(owner);
} else {
console.log(" > Transceiver pauser already correct, skipping");
console.log(" [=] Transceiver pauser already correct, skipping");
}
}
}
Loading