commit a4fc3c1ddaf645d4c67633b98fd3ce0b81a5c4e0 Author: lash Date: Tue Jul 25 09:49:50 2023 +0100 Initial commit diff --git a/solidity/Makefile b/solidity/Makefile new file mode 100644 index 0000000..c46e1c1 --- /dev/null +++ b/solidity/Makefile @@ -0,0 +1,12 @@ +SOLC = /usr/bin/solc + +all: + $(SOLC) --bin SwapPool.sol --evm-version byzantium | awk 'NR>3' > SwapPool.bin + $(SOLC) --abi SwapPool.sol --evm-version byzantium | awk 'NR>3' > SwapPool.json + $(SOLC) --metadata SwapPool.sol --evm-version byzantium | awk 'NR>3' > SwapPool.metadata.json + truncate -s -1 SwapPool.bin + +install: all + cp -v *.json ../python/erc20_swap_pool/data/ + cp -v *.bin ../python/erc20_swap_pool/data/ + diff --git a/solidity/SwapPool.sol b/solidity/SwapPool.sol new file mode 100644 index 0000000..8596902 --- /dev/null +++ b/solidity/SwapPool.sol @@ -0,0 +1,101 @@ +pragma solidity ^0.8.0; + +// Author: Louis Holbrook 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 +// SPDX-License-Identifier: AGPL-3.0-or-later +// File-Version: 1 +// Description: Voting contract using ERC20 tokens as shares + +contract SwapPool { + address registry; + address quoter; + uint256 feePpm; + address feeAddress; + uint256 public totalSupply; + mapping ( address => uint256 ) fees; + + constructor(address _tokenRegistry) { + registry = _tokenRegistry; + } + + function deposit(address _token, uint256 _value) public { + bool r; + bytes memory v; + + allowedToken(_token, registry); + + (r, v) = _token.call(abi.encodeWithSignature('transferFrom(address,address,uint256)', msg.sender, this, _value)); + require(r, "ERR_TOKEN"); + r = abi.decode(v, (bool)); + require(r, "ERR_TRANSFER"); + } + + function getFee(uint256 _value) private view returns (uint256) { + uint256 fee; + + fee = _value * feePpm; + fee /= 1000000; + + return fee; + } + + function getQuote(address _outToken, address _inToken, uint256 _value) private returns (uint256) { + bool r; + bytes memory v; + uint256 quote; + + if (quoter == address(0x0)) { + return _value; + } + + (r, v) = quoter.call(abi.encodeWithSignature('valueFor(address,address,uint256)', _outToken, _inToken, _value)); + require(r, "ERR_QUOTER"); + quote = abi.decode(v, (uint256)); + return quote; + } + + function withdraw(address _outToken, address _inToken, uint256 _value) public { + bool r; + bytes memory v; + uint256 netValue; + uint256 balance; + uint256 fee; + + fee = getFee(_value); + netValue = _value - fee; + netValue = getQuote(_outToken, _inToken, netValue); + + (r, v) = _outToken.call(abi.encodeWithSignature("balanceOf(address)", this)); + require(r, "ERR_TOKEN"); + balance = abi.decode(v, (uint256)); + require(balance >= netValue + fee, "ERR_BALANCE"); + + deposit(_inToken, _value); + + (r, v) = _outToken.call(abi.encodeWithSignature('transferFrom(address,address,uint256)', this, msg.sender, netValue)); + require(r, "ERR_TOKEN"); + r = abi.decode(v, (bool)); + require(r, "ERR_TRANSFER"); + + if (feeAddress != address(0)) { + fees[_outToken] += fee; + } + } + + function withdraw(address _token, uint256 _value) public returns (uint256) { + + } + + function allowedToken(address _token, address _registry) private { + bool r; + bytes memory v; + + if (_registry == address(0)) { + return; + } + + (r, v) = _registry.call(abi.encodeWithSignature('have(address)', _token)); + require(r, "ERR_REGISTRY"); + r = abi.decode(v, (bool)); + require(r, "ERR_UNAUTH_TOKEN"); + } +}