uniswap / v1-contracts Goto Github PK
View Code? Open in Web Editor NEW🐍Uniswap V1 smart contracts
License: GNU General Public License v3.0
🐍Uniswap V1 smart contracts
License: GNU General Public License v3.0
I'm proposing market limit orders that would allow users to purchase all the tokens up to a certain price point. This can be implemented as a wrapper contract for V1 and might make sense to be a core function for V2.
Currently, Uniswap lets users trade based on volume and enforce minimum returns on the volume of their trade. This trade type would be the counterpart and have the volume dynamically set based on the price Uniswap is offering to the user.
Eth to Token Market Limit:
ethToTokenSwapLimit(price_limit: uint256) -> uint256:
price_accuracy: uint256 = 10**9 #9 decimals of price precision
start_input_reserve: uint256 = self.balance
start_output_reserve: uint256 = self.token.balanceOf(self)
invariant: uint256 = start_input_reserve * start_output_reserve
target_input_reserve: uint256 = sqrt(invariant * target_price / price_accuracy)
trade_volume: uint256 = target_input_reserve - start_input_reserve
self.ethToTokenInput(trade_volume, 1, -1, msg.sender, msg.sender)
This method will purchase all the available tokens such that the cost of the last wei of token is <= price_limit
.
This works perfectly fine before you introduce fees to the system. Due to the nature of how Uniswap's pricing mechanism works, I am having a hard time predicting token cost with the introduction of fees. For example, simply setting price_limit
to price_limit * 997/1000
is too conservative a strategy, resulting in the cost of the last wei of token being well under the price_limit
.
It is my hope that someone smarter than me will be able to make this formula work with fees in the way Uniswap has implemented them.
Have you thought about implementing the PGP encryption architecture described here:
https://medium.com/fluidity/keyspace-end-to-end-encryption-using-ethereum-and-ipfs-87b04b18156b
This would prevent front running uniswap orders wouldn't it?
Not an issue per say, but wanted to discuss the usefulness of the min_liquidity
argument passed in the addLiquidity()
function. It seems to me that other than obtaining less % of the liquidity pool than expected, there isn't really much that can happen as the user can always withdraw the tokens they deposited. It also seems to be mainly a concern with newly created pools where the liquidity can change abruptly.
Any potential attacks I am not seeing that the min_liquidity
argument protect against? I see why the max_token is important as you might not want all your funds to be deposited if you also do something else with these tokens, but fail to see the practical relevance of the min_liquidity()
.
As I've wrote in my issue #19, for the Liquidity Providers in makes economical sense to add liquidity only if the price ratio of UniSwap contract assets' is more or less stable. For example a pair DAI <-> GUSD would make sense - the liquidity providers would not risk their funds too much, but they could still collect the fees.
Having two exchanges ETH <-> DAI and ETH <-> GUSD does not fix the price fluctuation problem for the liquidity providers, since they will still loose funds when Ether price changes.
I think this is the only alternative to implementing Oracle to update the prices - UniSwap could work very well in trading assets which relative price does not change much.
P.s. I am not sure how the Ether case should be handled in code - it must either have separate handling logic (more complexity) or it must be wrapped to WETH (extra gas).
A dapp wanting to know the approximate price of an asset can get the current exchange rate from Uniswap pretty easily. The problem is that someone can move the price reported by Uniswap at relatively little cost (0.6%) by sandwiching the price read transaction with a large Uniswap buy and a large Uniswap sell. This will cause the price to move up dramatically, followed by the price read, followed by restoring the price to its original level.
In order for Uniswap to be used as an Oracle, it needs to be sufficiently expensive to manipulate the current price reported by Uniswap. To achieve this, we can do a simple moving average or an exponential moving average of the price over time that can then be queried externally. This price will be "delayed" a bit, in the sense that it is more of a rough guess of about what the price is right now rather than an exact value, but for many tools that need an oracle this is sufficient. Manipulating it becomes much more expensive because in order to manipulate the price you must do so you must fight against arbitrageurs who are arbitraging your manipulated price back into line with everything else.
Every time someone buys or sells some particular asset, the EMA is updated like so:
const secondsSinceLastUpdate = now() - this.lastUpdateTimestamp
const historicWeight = Max(3600 - secondsSinceLastUpdate, 0)
const currentWeight = Min(secondsSinceLastUpdate, 3600)
this.ema = this.ema * historicWeight / 3600 + getCurrentPrice() * currentWeight / 3600
this.lastUpdateTimestamp = now()
executeTrade(...)
You would apply the same basic formula, just without the state updates or the executeTrade
line anytime someone queried for the EMA.
Every time someone buys or sells some particular asset, the SMA is updated like so:
const secondsSinceLastUpdate = now() - this.lastUpdateTimestamp
const secondsSinceBeginningOfHour = now() - now() % 3600
const historicWeight = Max(secondsSinceBeginningOfHour - secondsSinceLastUpdate, 0)
const currentWeight = Max(secondsSinceLastUpdate, secondsSinceBeginningOfHour)
this.sma = this.sma * historicWeight / secondsSinceBeginningOfHour + getCurrentPrice() * currentWeight / secondsSinceBeginningOfHour
this.lastUpdateTimestamp = now()
executeTrade(...)
Note: The current bucket should probably not be used for an oracle because at the beginning of the hour it is very cheap to manipulate, compared to the end of the hour.
The SMA version has the advantage of the cost of manipulation being higher because there are no points during the time period where manipulation is cheaper, it is expensive anytime during the hour. However, it has the disadvantage of being only reliable for historic hours (previous period), since the current hour will start off heavily manipulable.
The EMA version has the advantage of being continuous, it is always up to date and able to be used as an oracle at any time, and will trail the actual price closer than SMA. However, it has the disadvantage of manipulation being notably cheaper if done during the most recent minutes. For example, if you can control the price for a couple of blocks (e.g. buying blocks) you can have a fairly large impact on the EMA feed price since it weighs recent prices heavier than historic prices.
I came across Uniswap & the smart contracts that implement them a couple days ago & so far, I must say it seems to work great. I really like it.
However, looking through the source code, at least one flaw seemed to appear that I'd like to bring to your attention. I have not reviewed them thoroughly, and I'm not a vyper expert, so I definitely could be mistaken.
It looks like the exchange rate can change with each block as new swaps occur. But when you add or remove liquidity, the exchange rate may change between the block that the transaction was created and the mined block that it appears in. Since the arguments for these calls must be calculated exactly from the exchange rate, I think this could make it very difficult to use once activity increases.
Increasing the gas provided with the transaction would decrease the number of blocks between signing a transaction & it being mined, mitigating this somewhat. However, a very active market will be nearly impossible to add or remove liquidity, and when these calls fail, I think they will consume all of the gas provided for them. I think this will be quite hostile for people trying to participate in providing liquidity.
I think this is not an issue if the functions are always called by another contract so that calculations are always correct for the block the transaction is mined in.
I'm currently writing a wrapper contract in solidity to do that, among other things. I might switch to vyper if it always compiles code as efficient as yours. I've been away from coding smart contracts for a bit & vyper was new & untested then, so I've always written them in solidity.
Any thoughts?
In the Exchange Interface ABI json both return values from the function removeLiquidity
are named out
. When I generate typescript types from the ABI with typechain I get an error: error TS2300: Duplicate identifier 'out'
.
Please rename them with different names.
The repo has a bytecode directory but it does not specify whether the bytecode is the deployedBytecode or the constructor.
On line 191 in uniswap_exchange.vy (https://github.com/Uniswap/contracts-vyper/blob/76bb3300a0230335007e3a324aa35aa6d82351ff/contracts/uniswap_exchange.vy#L191), add and tokens_sold > 0 and min_eth > 0)
and remove min_eth > 0
on line 193
When calling ethToTokenPrice
from ethToToken
, self.balance
is updated (i.e, eth is already sent to the contract). As a result, eth_reserve
equals to eth_bal - eth_sold
.
However, when calling ethToTokenPrice
from getEthToTokenPrice
, the eth is not sent to the contract. As a result, eth_reserve
should equal to eth_bal
. That's why getEthToTokenPrice() should not directly call ethToTokenPrice().
One possible fix would be ethToTokenPrice
takes eth_sold
and eth_reserve
as arguments.
Hey,
This issue is similar to #25 except I'm using Etherlime instead of Truffle. Note that the solution applied in #25 (initial ETH value above 1000000000 wei) does not apply in my case.
In a nutshell I want to test a contract that will interact directly with Uniswap. My contract is written in Solidity and I want to do my tests on Ganache. I've imported the abi and bytecodes of the factory and the exchange from the Github repository and put them in UniswapFactory.json
and UniswapExchange.json
files. The 2 files have the same format as if they had been compiled by Etherlime (i.e. the json looks like {"contractName": , "abi": , "bytecode": }
.
My test file is
const etherlime = require('etherlime');
const UniswapFactory = require("../contracts/test/compiled/UniswapFactory");
const UniswapExchange = require("../contracts/test/compiled/UniswapExchange");
const ERC20 = require("../build/TestERC20");
const TestManager = require("../utils/test-manager");
describe("Test Uniswap", function () {
this.timeout(1000000);
const manager = new TestManager(accounts, 'ganache');
let infrastructure = accounts[0].signer;
describe("Add liquidity ", () => {
it('should create a liquidity pool with an initial liquidity', async () => {
deployer = manager.newDeployer();
// create factory
const uniswapFactory = await deployer.deploy(UniswapFactory);
const uniswapTemplateExchange = await deployer.deploy(UniswapExchange);
await uniswapFactory.initializeFactory(uniswapTemplateExchange.contractAddress);
const erc20 = await deployer.deploy(ERC20, {}, [infrastructure.address], 1000, 18);
// create liquidity pool
await uniswapFactory.from(infrastructure).createExchange(erc20.contractAddress);
const exchangeAddress = await uniswapFactory.getExchange(erc20.contractAddress);
const liquidityPool = await etherlime.ContractAt(UniswapExchange, exchangeAddress);
// add initial liquidity
await erc20.from(infrastructure).approve(liquidityPool.contractAddress, 200000000000);
const currentBlock = await manager.getCurrentBlock();
await liquidityPool.from(infrastructure).addLiquidity(1, 2000000000, currentBlock + 3000, {value: 2000000000});
});
});
}
The addLiquidity
call fails with
1) Test Uniswap
Add liquidity
should create a liquidity pool with an initial liquidity:
Error: VM Exception while processing transaction: invalid JUMP at 84f606a3a88732ef1ca37d72c04534e11d86fa43ccafd8759c3920f51b690aae/4398e3a71c988a9a4db928bc819681b95918a3bf:39
at getResult (node_modules/etherlime/node_modules/ethers/providers/json-rpc-provider.js:40:21)
at exports.XMLHttpRequest.request.onreadystatechange (node_modules/etherlime/node_modules/ethers/utils/web.js:111:30)
at exports.XMLHttpRequest.dispatchEvent (node_modules/xmlhttprequest/lib/XMLHttpRequest.js:591:25)
at setState (node_modules/xmlhttprequest/lib/XMLHttpRequest.js:610:14)
at IncomingMessage.<anonymous> (node_modules/xmlhttprequest/lib/XMLHttpRequest.js:447:13)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
Some of the test scenarios failed!
I have of course tested every property of the liquidity pool (token address, factory address, tokenSupply, ERC20 allowance) to make sure the contract is properly initialised before I call addLiquidity
, as well as the ETH and ERC20 balance of the infrastructure
account to make sure that none of the assert
of the addLiquidity
method throws.
What am I missing?
The function call in vyper is compiled to [assert, call[...]], which means that any exceptions occured in the setup
function will propagate to its caller (in this case, createExchange
). There is no need to return True in the setup function and assert it in the createExchange
.
Hi,
Great work @Uniswap! Tried writing a mail but did not get a response there. Hence, trying to reach out here.
We are interested in integrating Uniswap for our project Nexus Mutual. Just 2 quick questions here:
Hello,
This is a proposal for a radical change, so feel free to close this issue if Oracle solution is not acceptable from the project's standpoint of view.
Also, there are many ways to integrate Oracle, described below is just one of them.
I really liked the idea of UniSwap, but I also came to the conclusion that the UniSwap's price discovery model is just too expensive. Liquidity providers will be getting "punished" by arbitrage traders for every exchange rate shift.
For the liquidity providers not to loose funds there must be enough "end user" trading so that the collected 0.3% fee covers for the losses caused by price movements. However, the bigger the liquidity fund is, the more losses it will suffer from arbitrage.
For example:
We have created Uniswap 1.000 Ether and 100.000 DAI, when Ether price was $100. If Ether price moves to $150, the arbitrage trader will take away $5.000 (around 33 Ether) from the contract's liquidity to bring the price close to the correct one. To compensate for this move, the UniSwap contract needs to trade around $1.700.000, which is almost 10x the contract's total liquidity.
I think using an Oracle would be much cheaper than that.
I have the following proposal:
Create an Oracle contract which would have the following functionality:
The changes to Exchange contract:
I'm at the start of a project writing some ethereum contracts and I'm wanting to interact with Uniswap. I would love to know what the motivations were for switching from solidity (https://github.com/Uniswap/old-solidity-contracts) to vyper.
As is widely known at this point, Uniswap is not safe to use with ERC-777 tokens (even if you are only using the ERC-20 interface). More broadly speaking, the Uniswap contracts incorrectly assume that the token contract being called will not call out into any third party (potentially trader-controlled) code prior to returning.
Uniswap vNext should address this issue.
I love the idea of Uniswap and have been using it myself as a liquidity provider. However, at the moment, it seems that most of the profits are captured primarily by arbitrageurs.
The current state without an oracle:
The scenario with a price oracle would be:
The only function of a price oracle would be to ensure that the best possible arbitrage offered by Uniswap is never more than 2% relative to the market price to allow liquidity providers to capture value from price movements. The rest of the contract would still work the same way. Aside from introducing a point of centralization with an oracle and potentially higher gas fees, are there any other downsides with this approach?
It seems to not consider the fact that transfer()
and/or transferFrom()
of some ERC20 token contracts could return false
instead of throwing an exception in case of failure. Note that such a contract is still ERC20-compliant, as throwing an exception is recommended but not mandatory according to the ERC20 standard.
You may want to add the assertion on the return value, like (not sure about the exact syntax):
assert self.token.transfer(msg.sender, tokens)
EIP1155 and Uniswap would be a match made in heaven!
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
Are you going to add ERC228 interface support?
ethereum/EIPs#228
hey, developers of uniswap.
When using uniswap to trade tokenToToken, it turned out hard to decide value of min_eth_bought to pass in. I read contract's source code, if i understand the protocol correctly, there's already min_tokens_bought in tokenToTokenInput which user can use to control their risk against price changes. So my question is why you put min_eth_bought together with min_tokens_bought? What are the consequences if min_eth_bought is removed.
I am making an app that uses uniswap's contract also. So as I was trying to compile and deploy the master branch contracts on local testnet Ganache, I was constantly facing issues in the compilation. I think it's because of the old vyper language syntax. So I compiled other branch contracts and it compiled smoothly.
I want to ask can I use them for unit testing? Are they okay? Or what other ways are there to compile the old contract?
hi there
tried to add an exchange for 0x6251583e7d997df3604bc73b9779196e94a090ce
my HERC token
getting constant pending txs, when i click on them theres not etherscan hash
i managed to stack 3 txs before i gave up.
2 to add HERC 0x6251583e7d997df3604bc73b9779196e94a090ce as exchange
then
1 to unlock LOOM
While running pip install -r requirements.txt
I noticed this warning:
py-evm 0.2.0a33 has requirement eth-typing<2.0.0,>=1.1.0, but you'll have eth-typing 2.0.0 which is incompatible.
Full logs: https://gist.github.com/WyseNynja/e448d5dc68a1c5a733919fa54f4a1a2e
Uniswap is safe from re-entrancy for tokens that don't allow arbitrary callbacks in transfer functions. However, for tokens that do allow arbitrary callbacks (such as ERC777), a re-entrancy guard could make the contract more secure.
Implementation:
https://github.com/protofire/zeppelin-solidity/blob/master/contracts/ReentrancyGuard.sol
This would add ~5000-1000 gas until https://eips.ethereum.org/EIPS/eip-1283 is merged
Hello,
I have a small suggestion - currently Uniswap has about 2400 exchanges deployed. A few of the tokens (still) do no fully support ERC-20. The worst was BNB, but there are others - PKG, XYO etc.
Maybe it would be a good idea to a do a simple token compatibility test when creating a new exchange:
assert(token.transferFrom(msg.sender, address(this),1))
assert(token.transfer(msg.sender,1))
This small check would prevent people from loosing money.
What do you think? Maybe it is not too late to implement it in V2?
I attempted to add what is for me a fairly substantial amount of ETH and UBT to the v1 liquidity pool (which I already had a small position on). The tx ultimately ended up failing, and though the UBT still remains in my wallet, the 0.5791 ETH portion has disappeared from my wallet and doesn't seem to be accessible. There is a Retry Transaction button at the bottom of the failed TX but I am afraid to push it for fear of losing even more Ethereum.
How would I go about recovering the Ethereum that has seemingly been lost to this contract or is that even possible?
Here is the tx on the blockchain for reference.
https://etherscan.io/tx/0x178a1b9b783b908019d39ee2da7e4df4f3f1bd06a490d3a937a713572f6a6224
Hi everyone!
What about the idea to extend the exchange contract with
getTokenToTokenPrice
function?
The problem is, that if i try to get price for token to token i have to use:
getEthToTokenInputPrice
and
getTokenToEthInputPrice
that means the fees would be charged twice, but in the function getTokenToTokenPrice only once..
I would recommend EthToTokenPrice
and TokenToEthPrice
to be symmetric (so does EthToToken
and TokenToEth`)
e.g, Inside ethToTokenPrice
, you do not check eth_sold >0
. The check is done at the caller side(ethToToken
) . Then, you should do the same check in getEthToTokenPrice
.
Or you can move the check to ethToTokenPrice
and remove the check at ethToToken
.
Once you fixed the pattern in ethToToken, TokenToEth should be symmetric.
A Pool Factory extension to allow creation of pools and token swapping, where participants can have a choice to be compliant with their local or international laws.
Use case 1: Every non-US corporate and institutional liquidity providers (such as crypto hedge funds, market makers, OTC desks) is mandated, by US Government to pay taxes in the US for income received from US sources. To do so, liquidity providers must know the country of residence (but almost never identity) of Uniswap users who generated that income. To do so, such liquidity providers must have a "country of origin" report for all income they receive from liquidity pools.
Use case 2 - most (but not all) corporate and institutional liquidity providers must have an attestation that Uniswap users - specifically makers and takers (payers of the income generated by liquidity providers) were AML'ed by a 3rd party KYC provider such as onFido, Wyre, Jumio, etc. Almost never liquidity providers want an actual identity of a Uniswap user, - as long as there is a name of 3rd party AML provider and an anonymized customer ID behind 100% of the income received by such liquidity provider.
Use case 3 - most (but not all) corporate and institutional Uniswap users who want to swap tokens must have an attestation that their counterparty in Uniswap - were AML'ed by a 3rd party KYC provider such as onFido, Wyre, Jumio, etc. Almost never makers or takers want an actual identity of a Uniswap user, - as long as there is a name of 3rd party KYC provider and an anonymized customer ID behind 100% of the income received by such liquidity provider.
This proposal aims to extend Uniwap by adding a new optional feature for users: Know Your Customer (KYC), Anti-Money Laundering (AML), and Combating the Financing of Terrorism (CFT) regulations compliance. This feature will allow individuals and institutions alike to exchange and invest using Uniswap when these regulations apply.
There is a huge opportunity for exchanges such as Uniswap to attract individuals and institutions looking for investment opportunities that require to comply with regulations (e.g.: file reports with both the Internal Revenue Service and the U.S. Treasury, pay taxes on capital gains, etc.). Also, it is needed that every potential counterparty also comply with the regulations. This opportunity is very valuable even if they must go through a thorough KYC/AML/CFT process.
Current permissionless liquidity pools do not enforce KYC/AML validations, which is ok, however they prevent certain traders and investors from using Uniswap.
Pool Factory extension supporting only KYC’ed addresses to add/remove liquidity, swap and send tokens
In the current implementation only one pool can exist for a given token. We propose adding the possibility of having parallel sets of pools. Each pool in a set can only be used by a given smart contract (meaning, a set of pools is defined by the smart contract that can use those pools). The address of this contract is specified when the pool is created, and then all the interactions with those pools must go through that contract. That is: exchanges created this way will check that msg.sender
is equal to the proxy address that was used for creating the pool.
If this is supported, then a set of pools could be created so that they can only be used by addresses that went through a KYC/AML process. This can be done by checking that the account possess some KYC/AML token (see next section).
Note: Both approaches can be useful outside of this: Uniswap can use this “Sender address” for more customized pool factories, and this KYCProxy contract can be used as a proxy for any other contract that requires KYC.
In this diagram, we can see how the Registry works today, and how this new registry would work. Notice that the old Registry can continue to work, and the existing liquidity pools are still accessible. We have five different scenarios:
Wyre offers a service for validating KYC/AML information and it can associate this validation to an ethereum account. This is done by depositing a "KYC token" in that account's address. The KYCProxy contract could just check that this token exists for the transaction originator.
By using the Wyre widget, a full customer on-boarding with minimal coding KYC/AML widget can be integrated into Uniswap UI and flow.
Wyre is just one of the many KYC providers that can be plugged into a standard mechanism.
Some tokens do not follow ERC20 interface: OMG, ADX, PAY, MTL
The root of the problem: vyperlang/vyper#1383
I see a lot of BAD JUMP DESTINATION
transactions here: https://etherscan.io/address/0x3958b4ec427f8fa24eb60f42821760e88d485f7f
SNX token calls tokenFallback
on Uniswap contract in the middle of exchange and it seems Uniswap proxy handles this problem in a wrong way.
Proxy code is:
CALLDATASIZE
PUSH1 0x00
PUSH1 0x00
CALLDATACOPY
PUSH2 0x1000
PUSH1 0x00
CALLDATASIZE
PUSH1 0x00
PUSH20 0x2157a7894439191e520825fe9399ab8655e0f708
GAS
DELEGATE_CALL
ISZERO
PC
JUMPI
PUSH2 0x1000
PUSH1 0x00
RETURN
What does the latest part after DELEGATE_CALL
means can anyone describe what should happen after DELEGATE_CALL
reverts internally?
It seems Uniswap exchange called by another smart contract will eat all of its gas.
Hello!
First of all congrats for Uniswap, amazing project!
I'm starting a project that will be using Uniswap, and I've updated both contracts so they compile with latest Vyper version. Before creating a PR, I'd like to first confirm if this will be a relevant change for the project, and if yes what other critical parts of the project will need to be updated accordingly besides contracts source?
Thanks!
On line 48 in uniswap_exchange.vy (https://github.com/Uniswap/contracts-vyper/blob/76bb3300a0230335007e3a324aa35aa6d82351ff/contracts/uniswap_exchange.vy#L48), asserting msg.value > 0
is uncessary. That is because min_amount >0
and liquidity_minted > min_amount
already implies msg.value > 0
. Otherwise, liquidity_minted is 0 and liquidity_minted > min_amount
can not hold.
Using instruction for https://github.com/Uniswap/contracts-vyper
install of requirements.txt uses cytoolz, which in turn needs python3-dev
cd vyper
cd: vyper: No such file or directory
git reset --hard 35038d20bd9946a35261c4c4fbcb27fe61e65f78
fatal: Could not parse object '35038d20bd9946a35261c4c4fbcb27fe61e65f78'.
I'm trying to interact with uniswap through a truffle contract written in solidity 0.5.4. I have truffle migrate
able to deploy the contract bytecode that is checked into the repo. The abi is giving me issues, but I've worked around that for now (trufflesuite/truffle#1623). I have a test that AFAICT is successfully initializing the contract and setting up an exchange for a test ERC20 token. However, when I try to add liquidity, I get "invalid JUMP".
To ease debugging this, I should probably just push my whole repo up to GitHub, but I wasn't wanting to open source it just yet.
Here are some relevant pieces:
test/uniswap.js
:
const assert = require("chai").assert;
const UniswapExchange = artifacts.require("uniswap_exchange");
const IUniswapExchange = artifacts.require("IUniswapExchange");
const UniswapFactory = artifacts.require("uniswap_factory");
const IUniswapFactory = artifacts.require("IUniswapFactory");
const TutorialToken = artifacts.require("TutorialToken");
contract("uniswap_factory", accounts => {
it("... should be initializable through the interface", async () => {
await UniswapFactory.new();
const uniswapFactoryInstance = await IUniswapFactory.at(UniswapFactory.address);
// TODO: is this right?
await UniswapExchange.deployed();
await uniswapFactoryInstance.initializeFactory(UniswapExchange.address);
const savedExchangeTemplate = await uniswapFactoryInstance.exchangeTemplate();
assert.equal(savedExchangeTemplate, UniswapExchange.address);
const tokenCount = await uniswapFactoryInstance.tokenCount();
assert.equal(tokenCount, 0);
});
it("... should have a pool for TutorialToken", async () => {
await UniswapExchange.deployed();
await UniswapFactory.deployed();
const uniswapFactoryInstance = await IUniswapFactory.at(UniswapFactory.address);
await TutorialToken.deployed();
// TODO: return value of this is a tx receipt instead of the address like I expected. i'm doing something wrong
await uniswapFactoryInstance.createExchange(TutorialToken.address);
const tokenCount = await uniswapFactoryInstance.tokenCount();
assert.equal(tokenCount, 1);
const tutorialTokenUniswapAddress = await uniswapFactoryInstance.getExchange(TutorialToken.address);
const tutorialTokenUniswapInstance = await IUniswapExchange.at(tutorialTokenUniswapAddress);
const savedTutorialTokenAddress = await tutorialTokenUniswapInstance.tokenAddress();
assert.equal(savedTutorialTokenAddress, TutorialToken.address);
const savedFactoryAddress = await tutorialTokenUniswapInstance.factoryAddress();
assert.equal(savedFactoryAddress, UniswapFactory.address);
});
it("... should add some TutorialToken to the Uniswap pool", async () => {
await UniswapExchange.deployed();
await UniswapFactory.deployed();
const uniswapFactoryInstance = await IUniswapFactory.at(UniswapFactory.address);
const tutorialTokenInstance = await TutorialToken.deployed();
const tutorialTokenUniswapAddress = await uniswapFactoryInstance.getExchange(TutorialToken.address);
await tutorialTokenInstance.approve(tutorialTokenUniswapAddress, 100000000);
const tutorialTokenUniswapInstance = await IUniswapExchange.at(tutorialTokenUniswapAddress);
const balanceETH = web3.utils.toBN(await web3.eth.getBalance(accounts[0]));
assert(balanceETH.gt(1000));
const balance = await tutorialTokenInstance.balanceOf(accounts[0]);
assert.isAtLeast(balance.toNumber(), 1000);
const current_block = await web3.eth.getBlock(await web3.eth.getBlockNumber());
// TODO: why is this reverting?
await tutorialTokenUniswapInstance.addLiquidity(1000, 1000, current_block.timestamp + 300, {value: 1000});
});
});
Contract: uniswap_factory
✓ ... should be initializable through the interface (356200 gas)
✓ ... should have a pool for TutorialToken (250727 gas)
1) ... should add some TutorialToken to the Uniswap pool
Events emitted during test:
---------------------------
Approval(owner: <indexed>, spender: <indexed>, value: 100000000)
---------------------------
...
1) Contract: uniswap_factory
... should add some TutorialToken to the Uniswap pool:
Error: Returned error: VM Exception while processing transaction: invalid JUMP at c03c510f66214a6f07445cebf4484b987f6e99dba476ffd7e760307e3b57bcc3/c4954161e52bb1507cf4927b047cc0d904598510:39
at Object.ErrorResponse (node_modules/truffle/build/webpack:/~/web3-eth/~/web3-core-helpers/src/errors.js:29:1)
at node_modules/truffle/build/webpack:/~/web3-eth/~/web3-core-requestmanager/src/index.js:140:1
at Object.<anonymous> (node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:112:1)
at node_modules/truffle/build/webpack:/~/web3/~/web3-providers-ws/src/index.js:121:1
at Array.forEach (<anonymous>)
at W3CWebSocket.WebsocketProvider.connection.onmessage (node_modules/truffle/build/webpack:/~/web3/~/web3-providers-ws/src/index.js:98:1)
at W3CWebSocket._dispatchEvent [as dispatchEvent] (node_modules/truffle/build/webpack:/~/yaeti/lib/EventTarget.js:107:1)
at W3CWebSocket.onMessage (node_modules/truffle/build/webpack:/~/websocket/lib/W3CWebSocket.js:234:1)
at WebSocketConnection.<anonymous> (node_modules/truffle/build/webpack:/~/websocket/lib/W3CWebSocket.js:205:1)
at WebSocketConnection.processFrame (node_modules/truffle/build/webpack:/~/websocket/lib/WebSocketConnection.js:552:1)
at node_modules/truffle/build/webpack:/~/websocket/lib/WebSocketConnection.js:321:34
at processTicksAndRejections (internal/process/next_tick.js:74:9)
vyper --version 0.1.0b10
https://github.com/Uniswap/contracts-vyper/blob/master/contracts/uniswap_exchange.vy#L24
vyper.exceptions.InvalidTypeException: line 24: Unknown list type.
Not that Vyper uses RETURNDATASIZE, but the used memory location for returning data always contains nothing…
This results in the same as https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
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.