Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


The Ethereum implementation of the AdEx Protocol.

This replaces adex-core.

This repository implements OUTPACE (off-chain unidirectional trustless payment channel) and a gas abstraction layer called AdEx Identity.

Please note

  • Every channel will eventually expire (after validUntil), allowing the non-withdrawn portion of the initial deposit to be received back by whoever opened the channel.
  • Channels can be created with any ERC20 token; if the underlying token of a channel is insecure or malicious, that also compromises the channel as well; this is out of scope of this contract, since this is a fundamental issue with any system that uses ERC20s; needless to say, the user needs to be aware of what token they're using/earning
  • For more details on how OUTPACE channels work, please read the specs: AdEx Protocol and OUTPACE.


First, run ganache-cli in a separate terminal

truffle build # This is important cause js/IdentityProxyDeploy uses artifacts from there
npm test


The contract AdExCore from version v3.1.0, compiled with solc v0.5.6 is deployed here:

An Identity, initialized with no privileges, to be used as a basis for IdentityProxy:

An IdentityFactory, set up with the AdEx relayer:

And the Registry (now obsolete, no longer used):


All contracts here were compiled with solc v0.5.13.

The Identity, initialized with no privileges, to be used as a basis for IdentityProxy:

An IdentityFactory, set up with the AdEx relayer:

And the Staking:


The ADXSupplyController contract:

The ADXToken contract:

An instance of IdentityFactory used for staking:

The Staking contract:

The ADXFlashLoans contract:

The ADXLoyaltyPoolToken contract:

The ADXLoyaltyPoolIncentiveController contract:


The SupplyController contract:

New V5 SupplyController (increased cap to account for the to-be burned staking migration ADX):




Wallet (first demo)

IdentityFactory contract:

Identity contract:

Ambire Wallet

  • Factory: 0xBf07a0Df119Ca234634588fbDb5625594E2a5BCA
  • Base identity: 0x2A2b85EB1054d6f0c6c2E37dA05eD3E5feA684EF
  • QuickAccManager: 0xfF3f6D14DF43c112aB98834Ee1F82083E07c26BF
  • Batcher: 0x460fad03099f67391d84c9cc0ea7aa2457969cea

Same addresses on Ethereum, Polygon, BSC, Fantom, Arbitrum, Avalanche


truffle migrate --network mainnet
truffle migrate --network polygon
truffle migrate --network bsc

Verifying on etherscan

truffle compile
cat build/contracts/AdExCore.json | jq '.bytecode' # this is the bytecode you have to deploy
./scripts/ contracts/AdExCore.sol # this will output a bundled .sol code

Gas usage, from the tests

Measured with solc v0.5.6, commit d80fa80424ef7b8932399424f8d919d67b135a30

channelOpen: 69961
channelWithdrawExpired: 70470
channelWithdraw: 137117
execute: 89900
execRoutines: 114440
channelOpen, through execute: 115086
deploying an identity proxy through the IdentityFactory: 127549
addBond  73404
requestUnbond  34807
unbond  41770


This is not a part of the adex-protocol-eth source code, but it may be useful for anyone building on top of adex-protocol-eth who wishes to integrate with ENS.

  • ENS Contract mainnet address: 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
  • ENS PublicResolve mainnet address: 0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8
  • adex.eth node hash: 0x4e4e818e9467df5c5d1f8c399b11acc73ea24ad69e9c8e1ba6e5784a302c47d4
  • adex.eth subdomain registrar (adex.eth controller), compiled with solc v0.5.6: 0x7bc082552b1a195813ddb500600ce2b544d579cb

Code style and design principles

  • Minimalistic use of smart contracts in general
    • Avoid putting logic in SCs if it's outcome is controlled by a single entity anyway
    • Do not add complexity and centralization to address various "what ifs" that should be addressed off-chain, e.g. "what if users send tokens to this contract by accident"
  • Detailed tests for every contract
  • No Solidity warnings allowed
  • No modifiers allowed
  • Limited use of inheritance
  • No reentrancy guards allowed, instead we use the Checks-Effects-Interactions pattern
  • All requires should have an error message
  • No delegatecall upgradability; upgradability is achieved via off-chain social consensus
  • No emergency stops or pausability: it dilutes the value of smart contracts


Integration guide: Identity v5.2

EIP 1271 isValidSignature doesn't work until deployed

Since isValidSignature relies on calling the Identity contract through eth_call, we need that said Identity contract (proxy) is deployed. With the relayer, this is not true until the first transaction, due to the counterfactual deployment.

dApps can actually work around this by asking the user to deploy the proxy first.