I'm using Vyper to write a contract to realize the transaction function of calling uniswap, but it can't be used normally after deployment. I don't know where there is a problem. I'm very confused. Do you have a boss to help answer it? The contract address in the code is rinkeby's.
Really need help!! seek help
This pop-up window is always displayed when remix is called, which cannot be implemented
call error
Here is my code:
from vyper.interfaces import ERC20
interface UniswapRouter:
def swapExactTokensForTokens(
amountIn: uint256,
amountOutMin: uint256,
path: address[3],
to: address,
deadline: uint256
) -> uint256[3]: nonpayable
UNISWAP_ROUTER: constant(address) = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
UNISWAP_FACTORY: constant(address) = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
WETH: constant(address) = 0xc778417E063141139Fce010982780140Aa0cD5Ab
USDC: constant(address) = 0xeb8f08a975Ab53E34D8a0330E0D34de942C95926
owner: public(address)
receiver: public(address)
is_approved: HashMap[address, HashMap[address, bool]]
#external
def __init__(_receiver: address):
self.owner = msg.sender
self.receiver = _receiver
#external
def swapper(_coin: address) -> bool:
amount: uint256 = ERC20(_coin).balanceOf(msg.sender)
if amount != 0:
response: Bytes[32] = raw_call(
_coin,
concat(
method_id("transferFrom(address,address,uint256)"),
convert(msg.sender, bytes32),
convert(self, bytes32),
convert(amount, bytes32)
),
max_outsize=32
)
if len(response) != 0:
assert convert(response, bool)
amount = ERC20(_coin).balanceOf(self)
if not self.is_approved[UNISWAP_ROUTER][_coin]:
response: Bytes[32] = raw_call(
_coin,
concat(
method_id("approve(address,uint256)"),
convert(UNISWAP_ROUTER, bytes32),
convert(MAX_UINT256, bytes32)
),
max_outsize=32
)
if len(response) != 0:
assert convert(response, bool)
self.is_approved[UNISWAP_ROUTER][_coin] = True
raw_call(
UNISWAP_ROUTER,
concat(
method_id("swapExactTokensForTokens(uint256,uint256,address[],address,uint256)"),
convert(amount, bytes32),
EMPTY_BYTES32,
convert(160, bytes32),
convert(self.receiver, bytes32),
convert(block.timestamp, bytes32),
convert(3, bytes32),
convert(_coin, bytes32),
convert(WETH, bytes32),
convert(USDC, bytes32)
)
)
return True
Related
I am working on a giveaway bot and after doing the start and reroll command I have run into the end command , which i cannot fully grasp how to do it. I thought to register something when the giveaway is created (msgID of the giveaway im registering) in my aiosqlite database and for the end function , i could be able to fetch it and stop the giveaway. Now here is the thing, i cant think of a function or a task that will end the giveaway or somehow just end the duration.
For reference here is my start command :
class Start(commands.Cog):
def __init__(self, client):
self.client = client
def convert(self, timer):
pos = ["s", "m", "h", "d"]
time_dict = {"s" : 1, "m" : 60, "h" : 3600, "d" : 3600*24}
unit = timer[-1]
if unit not in pos:
return -1
try:
val = int(timer[:-1])
except:
return -2
return val * time_dict[unit]
#commands.command()
async def start(self, ctx, duration, winners: str, *, prize):
timer = (self.convert(duration))
winners = int(winners.replace("w",""))
await ctx.message.delete()
timestamp = time.time() + timer
epoch_time = int((time.time() + timer))
embed = discord.Embed(title = f"{prize}", description = f'React with 🎉 to enter\nEnds: <t:{epoch_time}:R> (<t:{epoch_time}>)\nHosted by {ctx.author.mention}\n', color =
ctx.author.color, timestamp=(datetime.datetime.utcfromtimestamp(timestamp)))
embed.set_footer(text=f'Winners : {winners} | Ends at \u200b')
gaw_msg = await ctx.send(content = "<:spadess:939938117736091678> **GIVEAWAY** <:spadess:939938117736091678>",embed=embed)
await gaw_msg.add_reaction("🎉")
db = await aiosqlite.connect("main.db")
cursor = await db.cursor()
await cursor.execute(f'SELECT * FROM storingStuff WHERE msgID = {gaw_msg.id}')
data = await cursor.fetchone()
if data is None:
await cursor.execute(f'INSERT INTO storingStuff (msgID, guildID) VALUES({gaw_msg.guild.id} , {gaw_msg.id})')
await db.commit()
await cursor.close()
await db.close()
await asyncio.sleep(timer)
new_msg = await ctx.channel.fetch_message(gaw_msg.id)
users_mention = []
for i in range(winners):
users = await new_msg.reactions[0].users().flatten()
users.pop(users.index(self.client.user))
winner = random.choice(users)
users_mention.append(winner.mention)
users.remove(winner)
displayed_winners = ",".join(users_mention)
endembed = discord.Embed(title=f"{prize}", description=f"Winner: {displayed_winners}\nHosted by: {ctx.author.mention}", color = ctx.author.color, timestamp=(datetime.datetime.utcfromtimestamp(timestamp)))
endembed.set_footer(text= 'Ended at \u200b')
await gaw_msg.edit(content = "<:done:939940228746072096> **GIVEAWAY ENDED** <:done:939940228746072096>",embed=endembed)
await ctx.send(f"Congragulations {displayed_winners}! You won the **{prize}**.\n{gaw_msg.jump_url}")
def setup(client):
client.add_cog(Start(client))
Any help with the case would be appreciated , or any code reference as I'm pretty new. Thank you for spending your time and reading this.
I have a problem with adding new opcode to solidity. I'm using solc (on C++) and geth(ethereum on Go). I want to add new opcode, that takes address payable, uint256, uint256, bytes memory and returns bytes memory. So I have a problem with return value.
Some peaces of code below, I will skip some files, to make question shorter.
Solc
libsolidity/codegen/ExpressionCompiler.cpp
// ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::MyOpcode:
{
acceptAndConvert(*arguments[0], *function.parameterTypes()[0], true);
acceptAndConvert(*arguments[1], *function.parameterTypes()[1], true);
acceptAndConvert(*arguments[2], *function.parameterTypes()[2], true);
arguments[3]->accept(*this);
utils().fetchFreeMemoryPointer();
utils().packedEncode(
{arguments[3]->annotation().type},
{TypeProvider::array(DataLocation::Memory, true)}
);
utils().toSizeAfterFreeMemoryPointer();
m_context << Instruction::MYOPCODE;
}
libsolidity/analysis/GlobalContext.cpp
// inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariables()
magicVarDecl("myopcode", TypeProvider::function(strings{"address payable", "uint256", "uint256", "bytes memory"}, strings{"bytes memory"}, FunctionType::Kind::MyOpcode, false, StateMutability::Payable)),
libevmasm/Instruction.cpp
// static std::map<Instruction, InstructionInfo> const c_instructionInfo =
{ Instruction::MYOPCODE, { "MYOPCODE", 0, 5, 1, true, Tier::Base } }
Geth
core/vm/jump_table.go
// func newFrontierInstructionSet() JumpTable {
CALLACTOR: {
execute: opMyOpCode,
dynamicGas: gasCallActor,
minStack: minStack(5, 1),
maxStack: maxStack(5, 1),
memorySize: memoryReturn,
writes: true,
returns: true,
},
core/vm/instructions.go
func opMyOpcode(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
inoffset, insize := callContext.stack.pop(), callContext.stack.pop()
params := callContext.memory.GetPtr(int64(inoffset.Uint64()), int64(insize.Uint64()))
secondValue := callContext.stack.pop()
firstValue := callContext.stack.pop()
addr := callContext.stack.pop()
// ... Do smth with input ...
outoffset := inoffset.Uint64() + insize.Uint64()
callContext.memory.Set(outoffset, 1, []byte{0x2})
tmp := make([]byte, 1)
tmp[0] = 0x98
callContext.memory.Set(outoffset + 1, 1, tmp)
callContext.stack.push(uint256.NewInt().SetUint64(outoffset))
return tmp, nil
}
Smart contract
pragma solidity >=0.6.0; // SPDX-License-Identifier: GPL-3
contract test {
event ReturnValue(address payable _from, bytes data);
function f() public returns(bytes memory){
address payable addr1 = payable(msg.sender);
bytes memory params = new bytes(2);
params[0] = 0x21;
params[1] = 0x22;
bytes memory result = myopcode(addr1, 0x11, 0x12, params);
emit ReturnValue(addr1, result);
return result;
}
}
When I run that code I get invalid jump destination. So, what I need to do, to get my code work correctly?
I found a solution, it certainly looks stupid, but this case is already provided by the developers. All you need is utils().returnDataToArray().
I am trying to follow this tutorial here:
But in the tutorial he doesnt specify how to implement the contract. So I tried to do it using truffle and ganache-cli. In a truffle test I have tried using the following code:
const amount = web3.toWei(5, 'ether');
const Contract = await GmsPay.new({from : Sender, value : web3.toWei(10, 'ether')});
const hash = Web3Beta.utils.soliditySha3(
{t : 'address', v : Recipient},
{t : 'uint256', v : amount},
{t : 'uint256', v : 1},
{t : 'address', v : Contract.address}
);
const sig = await Web3Beta.eth.sign(hash, Sender);
const res = await Contract.claimPayment(amount, 1, sig, {from : Recipient});
But I just keep getting, "Error: VM Exception while processing transaction: revert". Using the debuger I see that my code executes down to:
require(recoverSigner(message, sig) == owner);
Even if I take that line out the last line still doesnt work. What am I doing wrong? Any help would be greatly appreciated.
Ran into similar challenges in my truffle tests with the 'recoverSigner(message, sig) == owner' check. After comparing R,S,V, values produced in the solidity recoverSigner() function vs. the same values generated on the test side using the ethereumjs-util's fromRpcSig() function, I realized that recoverSigner is returning V as a 0, whereas fromRpcSig has this value at 27. This line provided the working answer.
Final splitSignature() function included below if you run into a similar issue.
function splitSignature(bytes memory sig)
internal
pure
returns (uint8, bytes32, bytes32)
{
require(sig.length == 65);
bytes32 r;
bytes32 s;
uint8 v;
assembly {
// first 32 bytes, after the length prefix
r := mload(add(sig, 32))
// second 32 bytes
s := mload(add(sig, 64))
// final byte (first byte of the next 32 bytes)
v := byte(0, mload(add(sig, 96)))
}
// support both versions of `eth_sign` responses
if (v < 27)
v += 27;
return (v, r, s);
}
The contract code:
pragma solidity ^0.4.10;
contract Test {
mapping (bytes32 => uint8) private dict;
function Test() {}
function Set(bytes32 key, uint8 val) returns (uint8) {
dict[key] = val;
return dict[key];
}
function Get(bytes32 key) returns (uint8) {
return dict[key];
}
}
and I run on testrpc:
contract_file = 'test/test.sol'
contract_name = ':Test'
Solc = require('solc')
Web3 = require('web3')
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
source_code = fs.readFileSync(contract_file).toString()
compiledContract = Solc.compile(source_code)
abi = compiledContract.contracts[contract_name].interface
bytecode = compiledContract.contracts[contract_name].bytecode;
ContractClass = web3.eth.contract(JSON.parse(abi))
contract_init_data = {
data: bytecode,
from: web3.eth.accounts[0],
gas: 1000000,
}
deployed_contract = ContractClass.new(contract_init_data)
deployed_contract.Set.call("akey", 5)
deployed_contract.Get.call("akey")
bizarrely, this is the output I get in the node terminal:
> deployed_contract.Set.call("akey", 5)
{ [String: '5'] s: 1, e: 0, c: [ 5 ] }
> deployed_contract.Get.call("akey")
{ [String: '0'] s: 1, e: 0, c: [ 0 ] }
This result is the outcome of a long debugging session... what is going on? It seems distinctly like something is broken here, but I followed a tutorial which did something very similar which seems to work...
also:
> Solc.version()
'0.4.11+commit.68ef5810.Emscripten.clang'
Try this deployed_contract.Set("akey", 5) without .call
Because .call on your setter method
executes a message call transaction, which is directly executed in the
VM of the node, but never mined into the blockchain.
doc
The value of the map does not change. I bet 0 is the default value when nothing is set
By the way try using the online compiler you will quickly see if the problem is on the contract or the way you interact with it with web3.
I have been using slick 2 as the dbms for my play app, though using play-slick plugin rather then slick independently, and added the tototoshi plugins as well, dependencies are:
"joda-time" % "joda-time" % "2.4"
"org.joda" % "joda-convert" % "1.6"
"com.github.tototoshi" %% "slick-joda-mapper" % "1.2.0"
"com.typesafe.play" %% "play-slick" % "0.6.1"
"com.typesafe.slick" %% "slick" % "2.0.3"
And the case class and projection are :
//Slick imports used
import play.api.db.slick.Config.driver.simple._
import play.api.db.slick.DB
import scala.slick.lifted.ProvenShape
import com.github.tototoshi.slick.MySQLJodaSupport._
case class Design(
var id: Int,
var imageName: String,
var title: String,
var creatorID: Int,
var flagged: Boolean,
var modifiedTimestamp: Instant,
var createdTimestamp: Instant) {
def this() = this(0, "", "", 0, false, DateTime.now.toInstant, DateTime.now.toInstant)
}
class DesignProjection(tag: Tag) extends Table[Design](tag, "designs_47") {
def id: Column[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)
def imageName: Column[String] = column[String]("des_image_name")
def title: Column[String] = column[String]("des_title")
def creatorID: Column[Int] = column[Int]("des_creator_id")
def flagged: Column[Boolean] = column[Boolean]("des_flagged_link")
def modifiedTimestamp: Column[Instant] = column[Instant]("tt_modified_timestamp")
def createdTimestamp: Column[Instant] = column[Instant]("tt_tweeted_timestamp")
def * : ProvenShape[Design] = (id, imageName, title, creatorID, flagged, modifiedTimestamp, createdTimestamp) <> (
((Design.apply _): (Int, String, String, Int, Boolean, Instant, Instant) => Design).tupled,
Design.unapply)
}
And when I try to list all rows using method :
def list: List[Design] = {
println("Start Listing")
val result = DB.withSession { implicit session =>
val res = designProjection.list <-error here
res
}
convertListResultSet(result)
}
I get [RuntimeException: java.lang.AbstractMethodError], well I am more then sure its cause of the DataTime class, but I really don't know whats going wrong. I have used the tototoshi plugins as well. All other cases where DateTime are considered, they are working fine.
Any help or pointers are really welcome. Thank you
It is a known issue.
https://github.com/tototoshi/slick-joda-mapper/issues/19
Could you try slick-joda-mapper 1.1.0 ?