ambiretech / adex-protocol-eth Goto Github PK
View Code? Open in Web Editor NEWEthereum implementation of the Ambire Protocol: Ambire Wallet contracts and AdEx payment channels
Home Page: https://www.ambire.com
License: MIT License
Ethereum implementation of the Ambire Protocol: Ambire Wallet contracts and AdEx payment channels
Home Page: https://www.ambire.com
License: MIT License
for now, solidity suffers from:
UnimplementedFeatureError: Calldata arrays with non-value base types are not yet supported by Solidity.
which means we have to use public
for all functions in AdExCore
and execute
/executeRoutines
in Identity
once this is solved we can make them external
IdentityDeployProxy.js: look into ways of generating bytecode w/o solc
Challenge description:
We use an Identity contract that reprensets each user (similar to multisig contracts, e.g. Gnosis safe); to save gas when deploying an identity for each user, we use delegatecall-based proxies.
The proxy contract bytecode is generated by the following JS: https://github.com/AdExNetwork/adex-protocol-eth/blob/master/js/IdentityProxyDeploy.js, for each user
There are comprehensive tests in test/TestIdentity
that show how that API is supposed to be used.
However, this JS library uses the full solc, which has some issues:
So, the challenge is to rewrite that JS to generate bytecode that does the same, but without having to ship solc (potentially by using a lighter weight EVM assember)
Submission requirements:
test/TestIdentity
pass without modificationjs/IdentityProxyDeploy.js
is preservedSubmission deadline:
Judging criteria:
Judging date:
Bounty:
currently truffle injects 0.x, which is horrible
simple contract based on/derived from the gnosis safe that allows gas abstractions for a user, and scheduled withdrawals
other implementations of gas abstractions seem dangerously complicated...
what we need is:
channelWithdraw
with any arguments for a certain channel; this allows scheduled withdrawals and does not have negative trust implications since channelWithdraw
always withdraws to msg.sender
; the only thing is, this message should allow only one such call, otherwise the relayer can withdraw your acc via tx feesso far, the repo should be theoretically compatible with EIP 712 signatures according ot the latest spec
to see if it's so in practice, review metamask and test
potentially have tests which use metamask's source code to sign EIP 712 msgs
also see AmbireTech/adex-platform#31
Implement a contract to stake ADX
It should:
slasherAddr
)Other ideas:
of the .sol file: https://github.com/AdExNetwork/adex-protocol-eth/blob/master/contracts/extra/Identity.sol
and of the libraries that come with it:
https://github.com/AdExNetwork/adex-protocol-eth/blob/master/js/Identity.js
https://github.com/AdExNetwork/adex-protocol-eth/blob/master/js/IdentityDeploy.js
goes around a data padding bug that f's up with a few erc20's using an ugly onlyPayloadSize
The goal is to allow users to easily register an ENS subdomain through their Identity contracts.
This would not require any changes to the Identity, as execute
can be used to trigger the name registrarion; it would simply require a registrar that will be set for adex.eth:
https://github.com/ensdomains/ens/blob/master/contracts/FIFSRegistrar.sol
See this as an example of what the Identity will do, once the user decides to register a username: https://github.com/UniversalLogin/UniversalLoginSDK/blob/master/universal-login-contracts/contracts/utils/ENSUtils.sol
Unlike the Universal login SDK, we won't force users into picking a username, it will be an entirely optional step that happens after registration
This is a simple task, but must be done within the team (hence no gitcoin-candidate) cause it requires nailing down a few important details; using a simple registrar won't be completely trustless, as we can change it at any time; to fix this, there must be a SC that owns the name completely; we will start with the simple FIFSRegistrar, and this could be an upgrade later down the line
a more trustless solution can be seen here: https://github.com/ensdomains/subdomain-registrar ; we won't use this, since we simply want a FIFSregistrar for our users
requirements:
see also:
Anybody can frontrun owner generated call of deployAndFund by either calling deploy or deployAndExecute making the owner's transaction fail. This forces the factory owner to fund the Identity contract in a different way, forcing additional transaction costs.
proposed way to fix this:
For now, option 2 is the frontrunner (lol)
features important gas cost optimizations, esp for the ABIEncoder v2 which we use for almost everything
move the JS libs out and have a separate test suite for them
it will be probably easiest to do tihs using a mock solidity contract that we can use through JS
if there's a safe way to do it, this will dramatically drop deployment costs
otherwise we won't be able to channelOpen
without a prior approve
even if we make users approve beforehand, the approved balance might run out
so we need this
currently it's possible for an advertiser to be their own publisher
in effect, they're basically doing a no-op, other than paying the validators
while it looks like something that we maybe shouldn't allow, this may have usecases actually, like if the same entity is acting both as a publisher and an advertiser, but nominates a third party validator to keep their data
Challenge description:
Uniswap is revolutionary - it showed us that it's possible to build an efficient and user friendly exchange on Ethereum by making the right design decisions.
However, it's smart contracts were built in vyper - which is not a bad thing, but coupled with the a popular bug in many erc20 contracts, means it's not usable for a lot of 2017 erc20 tokens, including ADX
The challenge is to build a uniswap version in solidity (perhaps based on https://github.com/PhABC/uniswap-solidity) that uses our own https://github.com/AdExNetwork/adex-protocol-eth/blob/master/contracts/libs/SafeERC20.sol library
This would come in handy to exchange ADX to ETH and vice versa; it should be able to interoperate with Uniswap itself, probably by wrapping the factory+registry - using the solidity-based market contracts for buggy ERC20 tokens and using the uniswap markets for non-buggy
More links:
https://twitter.com/phabcd/status/1101672268189581312?s=21
PhABC/uniswap-solidity#1
https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
Submission requirements:
Submission deadline:
Judging criteria:
Judging date:
Bounty:
Because advertisers need to sign messages, they can’t be smart contracts
Same applies to validators but it’s less of a problem
For now we are intentionally not addressing this problem, since there’s not a lot of practical use cases; if we need it, we can add a special function that registers a bid on chain, like in DEXY
Alternatively we can just solve this in the cosmos/polkadot versions; eg allow IBC messages to open bids too
If a validator permanently loses access to their domain name, or in some other way loses control over their endpoint URL (e.g. https://scratchy.validator.network), then all campaigns with it are permanently frozen and can't advance; no funds will be lost, but it's unpleasant
We deploy a separate ValidatorURLRegistry
contract, which allows validators to override the endpoint they set in the campaigns spec
The contract will expose a mapping endpoints
of the type address => string
, and you'd be able to set the endpoint for msg.sender
NOTE: whether the validator ID is always an ethereum address or it would allow ENS, depends on the adapter implementation; initially we only support addresses
when the channel enters an expired state, we can drop withdrawn[channelId]
and withdrawnByUser[channelId]
this will be a huge gas discount and great for on-chain state!
consider more events, potentially for: when execute
relays transactions, when executeRoutine
relays transactions, and when a routine auth fee is claimed
16 passing (18s)
3 failing
1) Contract: Identity
relay a tx:
error message is incorrect
+ expected - actual
-VM Exception while processing transaction: out of gas
+VM Exception while processing transaction: revert ONLY_IDENTITY_CAN_CALL
at expectEVMError (test/index.js:11:10)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
2) Contract: Identity
execute by sender:
error message is incorrect
+ expected - actual
-VM Exception while processing transaction: revert
+VM Exception while processing transaction: revert PRIVILEGE_NOT_DOWNGRADED
at expectEVMError (test/index.js:11:10)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
3) Contract: Identity
channelOpen and channelWithdrawExpired, via routines:
error message is incorrect
+ expected - actual
-VM Exception while processing transaction: revert
+VM Exception while processing transaction: revert NOT_EXPIRED
at expectEVMError (test/index.js:11:10)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:189:7)
the weird thing is that all other cases do return correct messages
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md
https://github.com/ethereum/EIPs/blob/master/assets/eip-712/Example.sol
https://github.com/godappslab/signature-verification/blob/master/contracts/TokenExchangeVerification.sol
https://github.com/uport-project/eip712-claims-experiments/search?q=DOMAIN_SEPARATOR&unscoped_q=DOMAIN_SEPARATOR
consider the possibility of paying fees and proving the fee is paid via OUTPACE channels
since the relayer can manipulate the validator set, or maliciously lock up user funds, this operation is not nearly as safe as the others
therefore, we should reflect that in the code comments and documentation
this should perhaps be a part of future iterations of the protocol, and would play nicely with the https://github.com/adexnetwork/adex-protocol#registry
the idea is to allow identity instances in which an address is allowed to open campaigns, but only with certain validators
this could be especially useful for grants that are only meant to be spent on AdEx advertising - e.g. you might get a grant on a SC that you can only redeem if you're calling into that SC through an Identity instance that's restricted in that way
the restricted validator set can be based on data from the Registry - e.g. the leader can only be one of the top N nodes from the advertiser side, and the follower can be only one of top N of the publisher side
Rename publisher/advertiser to supply/demand,
or, in the case of commitments, we can rename publisher/advertiser to beneficiery/giver
the rationale is that the interaction is not necessarily directly between publishers and advertisres
all identity calls are failing with revert
(effectively out of gas) if we don't increase the gasLimit
manually
related:
trufflesuite/ganache#367
trufflesuite/ganache#26
could mbe more, none of those seem on-point enough
If the code that we invoked through CALL reverts, can we get the revert reason string?
might be needed for #77
this is a very primitive version in C: https://github.com/ITSecLabs/EVM-Assembler/blob/master/easm.c
If this is used the same way as the old protocol, with 2 validators (publisher and advertiser), only 1 vote is required, which means the publisher can vote themselves and that will be sufficient.
This means, the dapp must always nominate a third validator.
right now, AdExCore implements OUTPACE so that'd be a better name
Check if aragonOS made any improvements to SafeERC20 so we can merge them back
https://github.com/aragon/aragonOS/blob/master/contracts/common/SafeERC20.sol
https://github.com/aragon/aragonOS/pull/469/files#diff-363c77684f4b2f5a3f3c94a40f0032e8R1
make an extra/ dir where we put everything not part of the OUTPACE stuff but still helpful to the protocol
this idea is for a ValidatorRegistry, where a validator can register their signing address against their wallet
Like so:
mapping (address => address)
The point of that is to allow validators to earn fees in different wallets than the ones they're using for signing
This registry component can also allow validators to use ENS and/or register their HTTPS endpoint(s) on-chain
there are a number of TODOs scattered over test/TestAdExCore.js
regarding negative cases (reverts, commitment timeouts) that should be tested
it would require writing the tests a bit smarter to avoid copypasta, but that should be trivial
consider implement a deployAndExecute
function, which would, in that order
the problem is that the order of 1 and 3 is fixed by the way identity contracts are created, so we cannot do 2 between them
as a solution, we can pay out the fee as an executable transaction
there's this: https://github.com/tdrerup/elliptic-curve-solidity/ (announcement: https://www.reddit.com/r/ethereum/comments/aunknt/a_pure_solidity_implementation_of_secp256r1/)
From my tests it consumes around 1m gas, which is bearable on mainnet on rare occasions; e.g. with the current gas and eth prices, it would cost around 2$
so this opens some doors:
rather than using the one-time addr trick, use CREATE2
We already have the ADEX
signature type which prefixes messages with a user friendly message (By signing this message, you acknowledge signing an AdEx bid with the hash:
)
However, we still show the raw bytes, which in ASCII look fairly ugly/scary; hex would be friendlier.
PLEASE NOTE: currently the internal consensus is to NOT use hex strings, but stick with the raw value; using hex strings adds too much on-chain complexity
This is an approach used by airswap, and spankchain:
https://etherscan.io/address/0xf91546835f756da0c10cfa0cda95b15577b84aa7#code
bytes memory sig = hexstrToBytes(substring(_sig, 2, 132));
// @dev Converts an hexstring to bytes
function hexstrToBytes(string _hexstr) public pure returns (bytes) {
uint len = bytes(_hexstr).length;
require(len % 2 == 0);
bytes memory bstr = bytes(new string(len / 2));
uint k = 0;
string memory s;
string memory r;
for (uint i = 0; i < len; i += 2) {
s = substring(_hexstr, i, i + 1);
r = substring(_hexstr, i + 1, i + 2);
uint p = parseInt16Char(s) * 16 + parseInt16Char(r);
bstr[k++] = uintToBytes32(p)[31];
}
return bstr;
}
// @dev Parses a hexchar, like 'a', and returns its hex value, in this case 10
function parseInt16Char(string _char) public pure returns (uint) {
bytes memory bresult = bytes(_char);
// bool decimals = false;
if ((bresult[0] >= 48) && (bresult[0] <= 57)) {
return uint(bresult[0]) - 48;
} else if ((bresult[0] >= 65) && (bresult[0] <= 70)) {
return uint(bresult[0]) - 55;
} else if ((bresult[0] >= 97) && (bresult[0] <= 102)) {
return uint(bresult[0]) - 87;
} else {
revert();
}
}
this will be convenient if we want other SCs to check the outcome, for example if the vote is a merkle root of a tree containing detailed info about the execution of that commitment
The idea is to allow users with quick (limited) accounts to recover their account
The process will work as follows:
looking for ways to make this simpler
this requires two potential changes to the identity contract:
lastInteractedWith
public timestampIdentityDeployProxy.js: look into ways of generating bytecode w/o solc
(for the previous challenge, and previous discussion, see #62)
We use an Identity contract that reprensets each user (similar to multisig contracts, e.g. Gnosis safe); to save gas when deploying an identity for each user, we use delegatecall-based proxies.
The proxy contract bytecode is generated by the following JS: https://github.com/AdExNetwork/adex-protocol-eth/blob/master/js/IdentityProxyDeploy.js, for each user
There are comprehensive tests in test/TestIdentity
that show how that API is supposed to be used.
However, this JS library uses the full solc, which has some issues:
So, the challenge is to rewrite that JS to generate bytecode that does the same, but without having to ship solc
The best solution would be use a simple EVM assembler, and to our knowledge, there's no such solution that's lightweight, embeddable in a web-based front-end, and well maintained
Such an assembler could be implemented in a web-friendly language (JS, TypeScript) or a language that compiles to WASM (Rust). Any solutions in languages other than JS/TypeScript/Rust will not be accepted.
test/TestIdentity
pass without modificationjs/IdentityProxyDeploy.js
is preserveddocument the gas cost differences between the old and the new protocol
the experience of making bindings (like js/Channel, js/Transaction) involves a lot of copy-paste right now
furthermore, it can really benefit from a good type system
since that's the validator that has to produce the new state
this might be useful: ethereum/solidity#4390
https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html
There's also a lot of useful information here such as the abi.encodeWithSignature
function
use the config from https://github.com/adexnetwork/adex-validator-stack-js
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.