Unable to verify smart contract on polygoanMumbai using VSCode - ethereum

I tried to verify my contract with constructor arguments but hardhat throwing that error everytime my smart contract file is given below
Domain.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;
// We first import some OpenZeppelin Contracts.
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import {StringUtils} from "./libraries/StringUtils.sol";
// We import another help function
import {Base64} from "./libraries/Base64.sol";
import "hardhat/console.sol";
contract Domains is ERC721URIStorage {
// Here's our domain TLD!
// Magic given to us by OpenZeppelin to help us keep track of tokenIds.
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
string public tld;
// We'll be storing our NFT images on chain as SVGs
string svgPartOne = '<svg xmlns="http://www.w3.org/2000/svg" width="270" height="270" fill="none"><path fill="url(#B)" d="M0 0h270v270H0z"/><defs><filter id="A" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="270" width="270"><feDropShadow dx="0" dy="1" stdDeviation="2" flood-opacity=".225" width="200%" height="200%"/></filter></defs><path d="M 64.285156 52.769531 L 105.675781 122.433594 C 106.085938 123.125 106.828125 123.550781 107.632812 123.550781 C 108.433594 123.550781 109.175781 123.125 109.589844 122.433594 L 128.328125 90.894531 L 147.0625 122.433594 C 147.476562 123.125 148.21875 123.550781 149.023438 123.550781 C 149.824219 123.550781 150.566406 123.125 150.980469 122.433594 L 192.367188 52.769531 C 192.789062 52.058594 192.800781 51.179688 192.394531 50.457031 C 191.988281 49.742188 191.230469 49.296875 190.410156 49.296875 L 169.480469 49.296875 C 168.671875 49.296875 167.921875 49.730469 167.511719 50.429688 L 151.105469 78.582031 C 150.464844 79.671875 150.832031 81.078125 151.917969 81.71875 C 153.003906 82.359375 154.398438 81.996094 155.035156 80.902344 L 170.785156 53.886719 L 186.390625 53.886719 L 149.023438 116.78125 L 130.984375 86.421875 L 150.980469 52.769531 C 151.402344 52.058594 151.410156 51.179688 151.003906 50.457031 C 150.601562 49.742188 149.84375 49.296875 149.023438 49.296875 L 128.089844 49.296875 C 127.28125 49.296875 126.53125 49.730469 126.125 50.429688 L 109.714844 78.582031 C 109.078125 79.671875 109.441406 81.078125 110.527344 81.71875 C 111.613281 82.359375 113.011719 81.996094 113.648438 80.902344 L 129.398438 53.886719 L 145 53.886719 L 126.375 85.234375 C 126.371094 85.242188 126.363281 85.253906 126.359375 85.265625 L 107.632812 116.78125 L 70.261719 53.886719 L 103.796875 53.886719 L 99.210938 62.371094 C 98.609375 63.480469 99.015625 64.875 100.125 65.480469 C 101.230469 66.085938 102.613281 65.675781 103.214844 64.5625 L 109.636719 52.6875 C 110.019531 51.976562 110.003906 51.113281 109.59375 50.417969 C 109.179688 49.722656 108.4375 49.296875 107.632812 49.296875 L 66.242188 49.296875 C 65.421875 49.296875 64.664062 49.742188 64.257812 50.457031 C 63.855469 51.179688 63.863281 52.058594 64.285156 52.769531" fill="#A274FF"/><defs><linearGradient id="B" x1="0" y1="0" x2="270" y2="270" gradientUnits="userSpaceOnUse"><stop stop-color="#120037"/><stop offset="1" stop-color="#120037" stop-opacity=".99"/></linearGradient></defs><rect x="50" y="211" rx="20" ry="20" width="170" height="40" style="stroke:white; stroke-width:3 ;opacity:0.9"/><text x="50%" y="240" rx="20" ry="20" font-size="25" fill="#FFF" font-family="Plus Jakarta Sans,DejaVu Sans,Noto Color Emoji,Apple Color Emoji,sans-serif" font-weight="bold" text-anchor="middle">.Web3Shift</text><text x="50%" y="200" font-size="27" fill="#fff" filter="url(#A)" font-family="Plus Jakarta Sans,DejaVu Sans,Noto Color Emoji,Apple Color Emoji,sans-serif" font-weight="bold" text-anchor="middle">';
string svgPartTwo = "</text></svg>";
mapping(string => address) public domains;
mapping(string => string) public records;
address payable public owner;
constructor(string memory _tld)
payable
ERC721("Web3Shift Name Service", "W3C")
{
owner = payable(msg.sender);
tld = _tld;
console.log("%s name service deployed", _tld);
}
function register(string calldata name) public payable {
require(domains[name] == address(0));
uint256 _price = price(name);
require(msg.value >= _price, "Not enough Matic paid");
// Combine the name passed into the function with the TLD
string memory _name = string(abi.encodePacked(name, ".", tld));
string memory just_name = string(abi.encodePacked(name));
// Create the SVG (image) for the NFT with the name
string memory finalSvg = string(
abi.encodePacked(svgPartOne, just_name, svgPartTwo)
);
uint256 newRecordId = _tokenIds.current();
uint256 length = StringUtils.strlen(name);
string memory strLen = Strings.toString(length);
console.log(
"Registering %s.%s on the contract with tokenID %d",
name,
tld,
newRecordId
);
// Create the JSON metadata of our NFT. We do this by combining strings and encoding as base64
string memory json = Base64.encode(
abi.encodePacked(
'{"name": "',
_name,
'", "description": "A domain on the Web3Shift name service", "image": "data:image/svg+xml;base64,',
Base64.encode(bytes(finalSvg)),
'","length":"',
strLen,
'"}'
)
);
string memory finalTokenUri = string(
abi.encodePacked("data:application/json;base64,", json)
);
console.log(
"\n--------------------------------------------------------"
);
console.log("Final tokenURI", finalTokenUri);
console.log(
"--------------------------------------------------------\n"
);
_safeMint(msg.sender, newRecordId);
_setTokenURI(newRecordId, finalTokenUri);
domains[name] = msg.sender;
_tokenIds.increment();
}
// This function will give us the price of a domain based on length
function price(string calldata name) public pure returns (uint256) {
uint256 len = StringUtils.strlen(name);
require(len > 0);
if (len == 1) {
return 3 * 10**17; // 5 MATIC = 5 000 000 000 000 000 000 (18 decimals). We're going with 0.5 Matic cause the faucets don't give a lot
} else if (len == 3) {
return 2 * 10**17; // To charge smaller amounts, reduce the decimals. This is 0.3
} else {
return 1 * 10**17;
}
}
// Other functions unchanged
function getAddress(string calldata name) public view returns (address) {
// Check that the owner is the transaction sender
return domains[name];
}
function setRecord(string calldata name, string calldata record) public {
// Check that the owner is the transaction sender
require(domains[name] == msg.sender);
records[name] = record;
}
function getRecord(string calldata name)
public
view
returns (string memory)
{
return records[name];
}
modifier onlyOwner() {
require(isOwner());
_;
}
function isOwner() public view returns (bool) {
return msg.sender == owner;
}
function withdraw() public onlyOwner {
uint256 amount = address(this).balance;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Failed to withdraw Matic");
}
}
hardhat.config.js
require("#nomiclabs/hardhat-waffle");
require("#nomiclabs/hardhat-etherscan");
const dotenv = require("dotenv");
dotenv.config();
//require("dotenv").config();
module.exports = {
solidity: "0.8.10",
etherscan: {
apiKey: {
goerli: "UGFT5V9QWSATQN8ERITGYZPT3VHN8EGZD3",
polygonMumbai: "TIG8FUTP9DKH2KN4957JCWIDWQSPQNEFKN",
}
},
networks: {
mumbai: {
url: process.env.url,
accounts: [process.env.key],
},
goerli: {
url: `https://eth-goerli.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
accounts: [process.env.goerli],
}
},
polygon: {
apiKey: {
polygonMumbai: "TIG8FUTP9DKH2KN4957JCWIDWQSPQNEFKN",
}
},
};
npx hardhat verify --network mumbai 0xB775e8D2A925836E216EcDea9E23A72c4AbF222f
(node:25360) ExperimentalWarning: stream/web is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Nothing to compile
Error in plugin #nomiclabs/hardhat-etherscan: The constructor for contracts/Domains.sol:Domains has 1 parameters
but 0 arguments were provided instead.
When I pass the argument then
npx hardhat verify --network mumbai 0xB775e8D2A925836E216EcDea9E23A72c4AbF222f 1
(node:26960) ExperimentalWarning: stream/web is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Nothing to compile
Successfully submitted source code for contract
contracts/Domains.sol:Domains at 0xB775e8D2A925836E216EcDea9E23A72c4AbF222f
for verification on the block explorer. Waiting for verification result...
We tried verifying your contract Domains without including any unrelated one, but it failed.
Trying again with the full solc input used to compile and deploy it.
This means that unrelated contracts may be displayed on Etherscan...
Successfully submitted source code for contract
contracts/Domains.sol:Domains at 0xB775e8D2A925836E216EcDea9E23A72c4AbF222f
for verification on the block explorer. Waiting for verification result...
Error in plugin #nomiclabs/hardhat-etherscan: The contract verification failed.
Reason: Fail - Unable to verify

Related

How to concatenate 2 String in Solidity and encode Keccak256?

i'm working at a smart-contract that has a merkle-tree function in it.
Basically i'm passing the proof from a firebase function that take in input the address and the n° of token reserved by the user, and gives as output the proof to the front-end that execute the smart-contract function.
The only thing i need to figure out is the leaf calculation, on the firebase function it is composed by encoding keccak256 the string in the array, composed by an eth address concatenated with the number of reserved tokens (0x38207d0e84edb04a57482c3769fe192617520373 + 3), in the smart contract instead, the leaf is calculated with the keccak256(abi.encodepacked(0x38207d0e84edb04a57482c3769fe1926175203733, 3), and it's not passing the verifiy...
I think these two methods of calculation are different in some part, can you help me?
I'm going to paste the code of both functions:
SOLIDITY
// 1. Address check, if the proof is valid
function isPrivateListed(
uint256 _addressReservedTokens,
bytes32[] memory _proof
) public view returns (bool) {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _addressReservedTokens);
return MerkleProof.verify(_proof, privateListRoot, leaf);
}
// 2. Mint function called from the front-end
function privateMint(
uint256 _mintAmount,
uint256 _addressReservedTokens,
bytes32[] calldata proof
) public payable {
require(privateOpen, "The private mint is not opened");
require(
isPrivateListed(_addressReservedTokens, proof),
"you are not in the private list"
);
uint256 supply = totalSupply();
require(supply + _mintAmount <= maxSupply, "max NFT limit exceeded");
uint256 owned = addressMintedBalance[msg.sender];
require(
owned + _mintAmount <= _addressReservedTokens,
"You have less nft reserved"
);
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(msg.sender, supply + i);
addressMintedBalance[msg.sender]++;
}
}
FIREBASE FUNCTION
// 1. Get parameters from the function called from client side
const walletAddress = data.walletAddress;
let whitelistAddresses = [
'0x38207d0e84edb04a57482c3769fe1926175203733',
'0x943926a8ff0000350d0b879a658fa52bcd4fca186',
];
// 2. Create a new array of `leafNodes` by hashing all indexes of the `whitelistAddresses`
// using `keccak256`. Then creates a Merkle Tree object using keccak256 as the algorithm.
const leafNodes = whitelistAddresses.map((addr) => keccak256(addr));
const merkleTree = new MerkleTree(leafNodes, keccak256, {
sortPairs: true,
});
// 3. Get root hash of the `merkleeTree` in hexadecimal format (0x)
const rootHash = merkleTree.getRoot();
const rootHashHex = merkleTree.getHexRoot();
// ***** ***** ***** CLIENT-SIDE ***** ***** ***** //
const claimingAddress = keccak256(walletAddress);
const hexProof = merkleTree.getHexProof(claimingAddress);
const verifyProof = merkleTree.verify(hexProof, claimingAddress, rootHash);
In solidity you're hashing a (20+32)-bytes element
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, _addressReservedTokens);
Since msg.sender is 20 bytes and _addressReservedTokens is 32 bytes, the output of abi.encodePacked() is something like this:
0x38207d0e84edb04a57482c3769fe1926175203730000000000000000000000000000000000000000000000000000000000000003
This is clearly different than 0x38207d0e84edb04a57482c3769fe1926175203733 used by firebase.
Also I'm not sure if the js keccak256 is interpreting that value as string or as bytes (in solidity it's bytes).
The best fix is probably changing the js code. You can write the correct whitelistAddresses using ethers, see here https://ethereum.stackexchange.com/questions/119990/how-to-mimic-abi-encodepacked-in-ethers

How to pass in arguments to a contract's constructor for initializing characters images and attributes

I have a contract like this that has a constructor like this:
constructor(
string[] memory characterNames,
string[] memory characterImageURIs,
uint256[] memory characterHp,
uint256[] memory characterAttackDmg,
string memory bossName,
string memory bossImageURI,
uint256 bossHp,
uint256 bossAttackDamage
) ERC721("Heroes", "HERO") {
for (uint256 i = 0; i < characterNames.length; i += 1) {
defaultCharacters.push(
CharacterAttributes({
characterIndex: i,
name: characterNames[i],
imageURI: characterImageURIs[i],
hp: characterHp[i],
maxHp: characterHp[i],
attackDamage: characterAttackDmg[i]
})
);
CharacterAttributes memory c = defaultCharacters[i];
console.log(
"Done initializing %s w/ HP %s, img %s",
c.name,
c.hp,
c.imageURI
);
}
bigBoss = BigBoss({
name: bossName,
imageURI: bossImageURI,
hp: bossHp,
maxHp: bossHp,
attackDamage: bossAttackDamage
});
console.log(
"Done initializing boss %s w/ HP %s, img %s",
bigBoss.name,
bigBoss.hp,
bigBoss.imageURI
);
_tokenIds.increment();
}
Question
for the characters names and HP and Attack... how should I type them is it in a JSON or in arrays or what?
for the imageURI how can I parse them to the constructor and where as I'm using Pinata IPFS to host my images?
Please if you can help me with this.
1- type for constructor arguments are already defined:
string[] = array of strings
string =string
uint (uint256) = 256 bits unsigned number ranging from 0 to 2²⁵⁶
2- constructor arguments mean, when you create the contract, you have to pass those parameters inorder to initialize the contracts. So you should already have them in hand.
you store the metadata in ipfs: an example would be like this:
{
"name": "name",
"description": "descruption",
"image": "ipfs://cid/name.jpeg"
}
So when you work in front-end, you make a request to ipfs Uri, to get the metadata:
// make a request with axios library
// this will store the above json data inside `metaData`.data
const metaData = await axios.get(tokenUri)
const data=metaData.data
From metadata, you get the imageUri as data.image

Solidity: Error when deploying the voting tutorial; problem with constructor and array?

I tried to reproduce the voting tutorial from the solidity homepage [https://solidity.readthedocs.io/en/v0.5.11/solidity-by-example.html#voting]. I encountered the following problem: The code can be compiled withouth an error, but when i want to "deploy" it in the JVM i always get errors. I think the problem is connected to the constructor who expects a bytes32 array.
Here are the error messages, depending on what parameter i used with the "Deploy" button in remix.
a) "Name1", "Name2"
--> creation of Ballot errored: Error encoding arguments: Error: types/values length mismatch (count={"types":1,"values":2},
value={"types":["bytes32[]"],"values":["Name1","Name2"]},
version=4.0.36)
b) ["Name1", "Name2"]
--> creation of Ballot errored: Error encoding arguments: Error: invalid bytes32 value (arg="", coderType="bytes32", value="Name1",
version=4.0.36)
c) "Name1"
--> creation of Ballot errored: Error encoding arguments: Error: expected array value (arg="", coderType="array", value="Name1",
version=4.0.36)
d) ["Name2"]
--> creation of Ballot errored: Error encoding arguments: Error: invalid bytes32 value (arg="", coderType="bytes32", value="Name2",
version=4.0.36)
e) Name3
--> creation of Ballot errored: Error encoding arguments: SyntaxError: Unexpected token N in JSON at position 1
f) 'Name3'
--> creation of Ballot errored: Error encoding arguments: SyntaxError: Unexpected token ' in JSON at position 1
g) ['Name4']
-->creation of Ballot errored: Error encoding arguments: SyntaxError: Unexpected token ' in JSON at position 2
pragma solidity >=0.4.22 <0.7.0;
/// #title Voting with delegation.
contract Ballot {
// This declares a new complex type which will
// be used for variables later.
// It will represent a single voter.
struct Voter {
uint weight; // weight is accumulated by delegation
bool voted; // if true, that person already voted
address delegate; // person delegated to
uint vote; // index of the voted proposal
}
// This is a type for a single proposal.
struct Proposal {
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
address public chairperson;
// This declares a state variable that
// stores a `Voter` struct for each possible address.
mapping(address => Voter) public voters;
// A dynamically-sized array of `Proposal` structs.
Proposal[] public proposals;
/// Create a new ballot to choose one of `proposalNames`.
constructor(bytes32[] memory proposalNames) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
// For each of the provided proposal names,
// create a new proposal object and add it
// to the end of the array.
for (uint i = 0; i < proposalNames.length; i++) {
// `Proposal({...})` creates a temporary
// Proposal object and `proposals.push(...)`
// appends it to the end of `proposals`.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
// Give `voter` the right to vote on this ballot.
// May only be called by `chairperson`.
function giveRightToVote(address voter) public {
// If the first argument of `require` evaluates
// to `false`, execution terminates and all
// changes to the state and to Ether balances
// are reverted.
// This used to consume all gas in old EVM versions, but
// not anymore.
// It is often a good idea to use `require` to check if
// functions are called correctly.
// As a second argument, you can also provide an
// explanation about what went wrong.
require(
msg.sender == chairperson,
"Only chairperson can give right to vote."
);
require(
!voters[voter].voted,
"The voter already voted."
);
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
/// Delegate your vote to the voter `to`.
function delegate(address to) public {
// assigns reference
Voter storage sender = voters[msg.sender];
require(!sender.voted, "You already voted.");
require(to != msg.sender, "Self-delegation is disallowed.");
// Forward the delegation as long as
// `to` also delegated.
// In general, such loops are very dangerous,
// because if they run too long, they might
// need more gas than is available in a block.
// In this case, the delegation will not be executed,
// but in other situations, such loops might
// cause a contract to get "stuck" completely.
while (voters[to].delegate != address(0)) {
to = voters[to].delegate;
// We found a loop in the delegation, not allowed.
require(to != msg.sender, "Found loop in delegation.");
}
// Since `sender` is a reference, this
// modifies `voters[msg.sender].voted`
sender.voted = true;
sender.delegate = to;
Voter storage delegate_ = voters[to];
if (delegate_.voted) {
// If the delegate already voted,
// directly add to the number of votes
proposals[delegate_.vote].voteCount += sender.weight;
} else {
// If the delegate did not vote yet,
// add to her weight.
delegate_.weight += sender.weight;
}
}
/// Give your vote (including votes delegated to you)
/// to proposal `proposals[proposal].name`.
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
// If `proposal` is out of the range of the array,
// this will throw automatically and revert all
// changes.
proposals[proposal].voteCount += sender.weight;
}
/// #dev Computes the winning proposal taking all
/// previous votes into account.
function winningProposal() public view
returns (uint winningProposal_)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
}
// Calls winningProposal() function to get the index
// of the winner contained in the proposals array and then
// returns the name of the winner
function winnerName() public view
returns (bytes32 winnerName_)
{
winnerName_ = proposals[winningProposal()].name;
}
}
You can't use strings since the function is expecting an array composed of bytes32 values. Link posted by #Ameesha (https://ethereum.stackexchange.com/questions/50310/how-to-pass-the-value-in-bytes32-array) shows how to encode the strings to bytes32. Additionally, I learned that passing values in single quotes is wrong, and not enclosing values in square brackets is also wrong... the correct way is to use double quotes around each hex value and use square brackets to represent as a list. So, for instance, "Proposal A", "Proposal B", "Proposal C" encodes to:
["0x50726f706f73616c204100000000000000000000000000000000000000000000",
"0x50726f706f73616c204200000000000000000000000000000000000000000000",
"0x50726f706f73616c204300000000000000000000000000000000000000000000"]
Pass the argument of []address as : [ "address","address1" ] instead of [address,address2].

Simple Open Auction example contract in Solidity docs doesn't pay beneficiary

I tried the Simple Open Auction example (https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#simple-open-auction) from the Solidity docs with ganache-cli and truffle. In migrations/2_deploy_contracts.js I set up:
var SimpleAuction = artifacts.require("./SimpleAuction.sol");
module.exports = function(deployer) {
deployer.deploy(SimpleAuction, 300, "0xe6ebc74aa685527a83c9e0df01b21acf0a1e8286");
};
With "0xe6ebc74aa685527a83c9e0df01b21acf0a1e8286" the address of account 1 in ganache.
In truffle console, I executed the following commands to simulate an auction (and I waited 300 seconds before calling auction.auctionEnd(), which succeeded):
auction = SimpleAuction.at(SimpleAuction.address)
account1 = web3.eth.accounts[1]
account2 = web3.eth.accounts[2]
account3 = web3.eth.accounts[3]
account4 = web3.eth.accounts[4]
auction.bid({from: account2, value: web3.toWei(10, "ether")})
auction.bid({from: account3, value: web3.toWei(13, "ether")})
auction.bid({from: account4, value: web3.toWei(15, "ether")})
auction.withdraw({from: account2})
auction.withdraw({from: account3})
auction.auctionEnd()
web3.fromWei(web3.eth.getBalance(account1).toString(), "ether")
web3.fromWei(web3.eth.getBalance(account2).toString(), "ether")
web3.fromWei(web3.eth.getBalance(account3).toString(), "ether")
web3.fromWei(web3.eth.getBalance(account4).toString(), "ether")
After this, the balances are:
100
99.9936296
99.9945537
84.9945537
Account 4 has won the auction and paid 15 eth, but I expected account 1 to have a balance of 115 eth, because this account is the beneficiary. I suppose the example code, which I copied verbatim, doesn't have a bug, so what am I doing wrong here?
The contract code is:
pragma solidity ^0.4.22;
contract SimpleAuction {
// Parameters of the auction. Times are either
// absolute unix timestamps (seconds since 1970-01-01)
// or time periods in seconds.
address public beneficiary;
uint public auctionEnd;
// Current state of the auction.
address public highestBidder;
uint public highestBid;
// Allowed withdrawals of previous bids
mapping(address => uint) pendingReturns;
// Set to true at the end, disallows any change
bool ended;
// Events that will be fired on changes.
event HighestBidIncreased(address bidder, uint amount);
event AuctionEnded(address winner, uint amount);
// The following is a so-called natspec comment,
// recognizable by the three slashes.
// It will be shown when the user is asked to
// confirm a transaction.
/// Create a simple auction with `_biddingTime`
/// seconds bidding time on behalf of the
/// beneficiary address `_beneficiary`.
constructor(
uint _biddingTime,
address _beneficiary
) public {
beneficiary = _beneficiary;
auctionEnd = now + _biddingTime;
}
/// Bid on the auction with the value sent
/// together with this transaction.
/// The value will only be refunded if the
/// auction is not won.
function bid() public payable {
// No arguments are necessary, all
// information is already part of
// the transaction. The keyword payable
// is required for the function to
// be able to receive Ether.
// Revert the call if the bidding
// period is over.
require(
now <= auctionEnd,
"Auction already ended."
);
// If the bid is not higher, send the
// money back.
require(
msg.value > highestBid,
"There already is a higher bid."
);
if (highestBid != 0) {
// Sending back the money by simply using
// highestBidder.send(highestBid) is a security risk
// because it could execute an untrusted contract.
// It is always safer to let the recipients
// withdraw their money themselves.
pendingReturns[highestBidder] += highestBid;
}
highestBidder = msg.sender;
highestBid = msg.value;
emit HighestBidIncreased(msg.sender, msg.value);
}
/// Withdraw a bid that was overbid.
function withdraw() public returns (bool) {
uint amount = pendingReturns[msg.sender];
if (amount > 0) {
// It is important to set this to zero because the recipient
// can call this function again as part of the receiving call
// before `send` returns.
pendingReturns[msg.sender] = 0;
if (!msg.sender.send(amount)) {
// No need to call throw here, just reset the amount owing
pendingReturns[msg.sender] = amount;
return false;
}
}
return true;
}
/// End the auction and send the highest bid
/// to the beneficiary.
function auctionEnd() public {
// It is a good guideline to structure functions that interact
// with other contracts (i.e. they call functions or send Ether)
// into three phases:
// 1. checking conditions
// 2. performing actions (potentially changing conditions)
// 3. interacting with other contracts
// If these phases are mixed up, the other contract could call
// back into the current contract and modify the state or cause
// effects (ether payout) to be performed multiple times.
// If functions called internally include interaction with external
// contracts, they also have to be considered interaction with
// external contracts.
// 1. Conditions
require(now >= auctionEnd, "Auction not yet ended.");
require(!ended, "auctionEnd has already been called.");
// 2. Effects
ended = true;
emit AuctionEnded(highestBidder, highestBid);
// 3. Interaction
beneficiary.transfer(highestBid);
}
}
When I call auction.auctionEnd() before the 300 seconds, I get an exception "Auction not yet ended", which is what it is supposed to do:
truffle(development)> auction.auctionEnd()
Error: VM Exception while processing transaction: revert Auction not yet ended.
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)
When I call it after 300 seconds, I get a transaction and an event AuctionEnded, so it looks like the now >= auctionEnd condition is met:
truffle(development)> auction.auctionEnd()
{ tx: '0x480208cd6c4ac3580e7dcc3aa7e64cd0e7b5e11d5bea75e4769b554767158e35',
receipt:
{ transactionHash: '0x480208cd6c4ac3580e7dcc3aa7e64cd0e7b5e11d5bea75e4769b554767158e35',
transactionIndex: 0,
blockHash: '0xfde6956d9c7d6e99235606b70e11161965ddf832063e572a87df00c14484e5a1',
blockNumber: 12,
gasUsed: 76921,
cumulativeGasUsed: 76921,
contractAddress: null,
logs: [ [Object] ],
status: '0x1',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000100000000040000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs:
[ { logIndex: 0,
transactionIndex: 0,
transactionHash: '0x480208cd6c4ac3580e7dcc3aa7e64cd0e7b5e11d5bea75e4769b554767158e35',
blockHash: '0xfde6956d9c7d6e99235606b70e11161965ddf832063e572a87df00c14484e5a1',
blockNumber: 12,
address: '0xef0a6e95779240516e8a05039f97968f727c4f18',
type: 'mined',
event: 'AuctionEnded',
args: [Object] } ] }
Hopefully this can help you. I think you missed time travel part.
// test/SimpleAuction.js
const sa = artifacts.require("SimpleAuction");
contract('SimpleAuction', async function(accounts) {
/**
* TimeTravel function - can move this to helper file
* https://www.reddit.com/r/ethdev/comments/6n65ar/using_testrpc_and_truffles_built_in_js_tests_how/dk7357l/
*/
const timeTravel = function (time) {
return new Promise((resolve, reject) => {
web3.currentProvider.sendAsync({
jsonrpc: "2.0",
method: "evm_increaseTime",
params: [time], // 86400 is num seconds in day
id: new Date().getTime()
}, (err, result) => {
if(err){ return reject(err) }
return resolve(result)
});
})
}
var sa_instance;
var highest_bid = 2; // ether
var bob = accounts[1];
var alice = accounts[2];
var john = accounts[3];
var beneficiary = accounts[accounts.length - 1]; // last account in Ganache
var beneficiary_initial_balance;
before(async function() {
sa_instance = await sa.new(300, beneficiary);
var bib_balance_wei = await web3.eth.getBalance(beneficiary);
var bib_balance_eth = web3.fromWei(web3.toDecimal(bib_balance_wei), "ether");
beneficiary_initial_balance = parseInt(bib_balance_eth);
})
it("Bob bids with 1 ETH", async function() {
await sa_instance.bid({from: bob, value: web3.toWei(1, "ether")})
var sa_balance_wei = await web3.eth.getBalance(sa_instance.address);
var sa_balance_eth = web3.fromWei(web3.toDecimal(sa_balance_wei), "ether");
assert.equal(sa_balance_eth, 1);
})
it("Alice bids with 2 ETH", async function() {
await sa_instance.bid({from: alice, value: web3.toWei(highest_bid, "ether")})
var sa_balance_wei = await web3.eth.getBalance(sa_instance.address);
var sa_balance_eth = web3.fromWei(web3.toDecimal(sa_balance_wei), "ether");
assert.equal(sa_balance_eth, 3);
})
it("Bob can withdraw his 1 ETH back", async function() {
await sa_instance.withdraw({from: bob})
var sa_balance_wei = await web3.eth.getBalance(sa_instance.address);
var sa_balance_eth = web3.fromWei(web3.toDecimal(sa_balance_wei), "ether");
assert.equal(sa_balance_eth, highest_bid);
})
it("Anyone can end the auction when it's due", async function() {
await timeTravel(300);
await sa_instance.auctionEnd({from: john});
})
it("Contract balance left with 0 ETH", async function() {
var sa_balance_wei = await web3.eth.getBalance(sa_instance.address);
var sa_balance_eth = web3.fromWei(web3.toDecimal(sa_balance_wei), "ether");
assert.equal(sa_balance_eth, 0);
})
it("And beneficiary is now 2 ETH richer", async function() {
var bib_balance_wei = await web3.eth.getBalance(beneficiary);
var bib_balance_eth = web3.fromWei(web3.toDecimal(bib_balance_wei), "ether");
var expected_new_beneficiary_balance = beneficiary_initial_balance + highest_bid;
assert.equal(expected_new_beneficiary_balance, bib_balance_eth);
})
})
Did auctionEnd() succeed?
Most likely require(now >= auctionEnd) is not satisfied thus auctionEnd() failed.
Update: Debugged the contract myself, the transfer is successful. Beneficiary address is: 0xe6ebc74aa685527a83c9e0df01b21acf0a1e8286 not account1. So the contract works as expected, there is no problem. Check the balance of beneficiary address, you will see it has 15 ether.
Clarification:
This is the deployment instruction:
module.exports = function(deployer) {
deployer.deploy(SimpleAuction, 300, "0xe6ebc74aa685527a83c9e0df01b21acf0a1e8286");
};
So you set beneficiary address as: 0xe6ebc74aa685527a83c9e0df01b21acf0a1e8286.
And this is the transfer instruction inside auctionEnd():
beneficiary.transfer(highestBid);
So after the execution, if you run the following command you will see that beneficiary has 15 ether.
web3.eth.getBalance("0xe6ebc74aa685527a83c9e0df01b21acf0a1e8286")
BigNumber { s: 1, e: 19, c: [ 150000 ] }

solidity - get return value of delegatecall with assembly

I have a contract A and a contract B.
Contract A declares this function:
function getIntValue() constant returns (uint);
What would be the appropriate assembly code to delegatecall contract A's getIntValue function from B? I'm not yet very experienced with assembly so I only have this so far which doesn't work:
function getContractAIntValue() constant returns (uint c) {
address addr = address(contractA); // contract A is stored in B.
bytes4 sig = bytes4(sha3("getIntValue()")); // function signature
assembly {
let x := mload(0x40) // find empty storage location using "free memory pointer"
mstore(x,sig) // attach function signature
let status := delegatecall(sub(gas, 10000), addr, add(x, 0x04), 0, x, 0x20)
jumpi(invalidJumpLabel, iszero(status)) // error out if unsuccessful delegatecall
c := mload(x)
}
}
Maybe you have solved it cause was asked more than one year ago, but in case some is still looking for it...
address addr = address(contractA); // contract A is stored in B.
bytes memory sig = abi.encodeWithSignature("getIntValue()"); // function signature
// solium-disable-next-line security/no-inline-assembly
assembly {
let result := delegatecall(sub(gas, 10000), addr, add(sig, 0x20), mload(sig), 0, 0)
let size := returndatasize
let ptr := mload(0x40)
returndatacopy(ptr, 0, size)
// revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas.
// if the call returned error data, forward it
switch result case 0 { revert(ptr, size) }
default { return(ptr, size) }
}