OneSec is a suite of smart contracts that allows users to bridge tokens between ICP and EVM chains such as Arbitrum, Base, and Ethereum. More chains like Bitcoin and Solana will be added in the future.
The main smart contract runs on ICP and interacts with ERC20 contracts on EVM chains using two key features of ICP:
- Threshold ECDSA for writing to EVM: the main smart contract can sign EVM transactions without storing the private key on a single node.
- HTTP Outcalls for reading from EVM: the main smart contract can fetch EVM blocks and events by asking multiple ICP nodes to make HTTP requests to multiple EVM RPC nodes each and pick the correct response with a consensus algorithm.
These two features are sufficient to build a decentralized and trustless bridge without a single point of failure.
Flow example: bridging USDC from Arbitrum to ICP
Let's walk through an example of Alice bridging 1 USDC from Arbitrum to Bob's account on ICP.
The first phase of bridging happens on the Arbitrum chain where Alice locks 1 USDC using OneSec's locker smart contract. If locking is successful, then the smart contract emits an event confirming that Alice indeed locked 1 USDC for Bob.

On the ICP side, the main OneSec contract fetches events from the Arbitrum chain using the HTTP outcalls feature of ICP. For security, each ICP node queries each EVM RPC node. Note that there are two consensus rounds happening here. Once the event is fetched and validated, the main contract calls the USDC ledger on ICP to mint 1 USDC to Bob.

$ dfx canister call usdc_ledger icrc2_approve "(record { amount = $AMOUNT : nat; spender = record { owner = principal \"$(dfx canister id key_token)\"; subaccount = null; }; })" $ dfx canister call key_token transfer "(record { source = record { chain = variant { ICP }; token = variant { oUSDC }; account = variant { Icp = record { owner = principal \"$FROM\"; subaccount = null; } }; amount = $AMOUNT: nat; }; destination = record { chain = variant { $EVM_CHAIN }; token = variant { USDC }; account = variant { Evm = record { address = \"$TO\" } }; }; },)"
Flow example: bridging USDC from ICP to Arbitrum
In order to bridge 1 USDC from ICP to Arbitrum, Alice calls the main smart contract of OneSec, which then calls the USDC ledger and burns $1 from Alice's account. After that the main contract prepares an Aributrm transaction and uses the Threshold ECDSA feature of ICP to sign the transaction.

When the transaction is signed, the main contract sends the transaction to Arbitrum using HTTP outcalls and EVM RPC nodes. Note that it doesn't matter how a signed transaction reaches Arbitrum because its signature will be validated before execution. In order to speed up this step, OneSec uses off-chain relayers to deliver signed transactions to the target chain. Once the transaction is delivered and executed, it transfers 1 USDC to Bob's address.

ERC20 Contracts
- ICP: 0x00f3C42833C3170159af4E92dbb451Fb3F708917
- ckBTC: 0x919A41Ea07c26f0001859Bc5dcb8754068718Fb7
- BOB: 0xecc5f868AdD75F4ff9FD00bbBDE12C35BA2C9C89
Ledger Canisters
- USDC: 53nhb-haaaa-aaaar-qbn5q-cai
- USDT: ij33n-oiaaa-aaaar-qbooa-cai
- cbBTC: io25z-dqaaa-aaaar-qbooq-cai