I'd like to include an internal method in my contract that allows the creation of a new uint256 in storage named by a parameter. Something like:
function createUint (string memory _name) internal {
/*
* creates a new uint256 named _name in storage
*/
}
My guess is that it would require inline assembly, but I can't figure out how
How about a mapping?
mapping(string => uint256) myMap;
function setValue(string memory name, uint256 value) internal {
myMap[name] = value;
}
Related
The domain message is:
struct Offer{
address from;
address to;
uint256 nonce;
uint256[] tokenIds;
uint256 duration;
}
bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 constant OFFER_TYPEHASH = keccak256(
"Offer(address from,address to,uint256 nonce,uint256[] memory tokenIds,uint256 duration)"
);
function hash(Offer memory offer) public pure returns (bytes32) {
return keccak256(abi.encode(
OFFER_TYPEHASH,
offer.from,
offer.to,
offer.nonce,
keccak256(abi.encodePacked(offer.tokenIds)),
offer.duration
));
}
function verify(Offer memory offer, uint8 v, bytes32 r, bytes32 s) public view returns (bool) {
// Note: we need to use encodePacked here instead of encode.
bytes32 digest = keccak256(abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
hash(offer)
));
return ecrecover(digest, v, r, s) == ExpectedAddress;
}
I can't resolve issue with array when doing v4 signature.
If I removed tokenIds array from Offer struct, and OfferTypeHash, and also from hash func: everything works well as expected, I can verify signature via web3 and contract.
When I put tokenIds array to struct, I can't verify signature.
I googled and tried a lot of examples like:
I use this for hashing the offer:
keccak256(abi.encodePacked(array))
function hash(Offer memory offer) public pure returns (bytes32) {
return keccak256(abi.encode(
OFFER_TYPEHASH,
offer.from,
offer.to,
offer.nonce,
keccak256(abi.encodePacked(offer.tokenIds)),
offer.duration
));
}
keccak256(abi.encode(array))
keccak256(abi.encodePacked(array))
function hash(Offer memory offer) public pure returns (bytes32) {
return keccak256(abi.encode(
OFFER_TYPEHASH,
offer.from,
offer.to,
offer.nonce,
keccak256(abi.encode(offer.tokenIds)),
offer.duration
));
}
Even without Keccak:
function hash(Offer memory offer) public pure returns (bytes32) {
return keccak256(abi.encode(
OFFER_TYPEHASH,
offer.from,
offer.to,
offer.nonce,
keccak256(abi.encode(offer.tokenIds)),
offer.duration
));
}
I can't figure out: why keccak256(abi.encode is not doing the job?
I have only seen that the mapping variables are declared as storage variables.
I'd like to know if I can declare a mapping variable inside the function in Solidity.
No, its not possible because mappings cannot be created dynamically, you have to assign them from a state variable. Yet you can create a reference to a mapping, and assign a storage variable to it.
Yet, you can encapsulate the mapping in a contract, and use it in another by instantiating a new contract containing that mapping, this is the most approximated way of "declaring" a mapping inside a function.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract MappingExample {
mapping(address => uint) public balances;
function update(uint newBalance) public {
balances[msg.sender] = newBalance;
}
}
contract MappingUser {
function f() public returns (uint) {
MappingExample m = new MappingExample();
m.update(100);
return m.balances(address(this));
}
}
Taken form the docs:
Mappings in solidity are always stored in the storage and declared top-level as docs say.
But you declare a mapping inside a function if it refers to a top-level mapping inside a function.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract MappingInFunction {
mapping (uint => string) public Names;
uint public counter;
function addToMappingInsideFunction(string memory name) public returns (string memory localName) {
mapping (uint => string) storage localNames = Names;
counter+=1;
localNames[counter] = name;
return localNames[counter];
// we cannot return mapping in solidity
// return localNames;
}
}
Even though I am not sure what would be the use case but referring to top-level mapping inside addToMappingInsideFunction is a valid syntax.
I have created a solidity that record data CRUD like where I can create read update delete but I want to create a readAll function wondering how can I write in solidity since I write like below it does not work. For calling with id it return the correct but not readAll. Looking forward for your help <3
example
function readAllTask() public view returns (uint, uint256, uint256) {
return (tasks.id, tasks.stackAddress, tasks.nftId); <============= return everything
}
pragma solidity ^0.8.6;
contract RecordData {
struct Task {
uint id;
uint256 stackAddress;
uint256 nftId;
}
Task[] tasks;
uint nextId; // default value 0, add public to see the value
function createTask(uint256 _stackAddress, uint256 _nftId) public {
tasks.push(Task(nextId, _stackAddress, _nftId));
nextId++;
}
function findIndex(uint _id) internal view returns (uint) {
for (uint i = 0; i < tasks.length; i++) {
if (tasks[i].id == _id) {
return i;
}
}
revert("Task not found");
}
function updateTask(uint _id, uint256 _stackAddress, uint256 _nftId) public {
uint index = findIndex(_id);
tasks[index].stackAddress = _stackAddress;
tasks[index].nftId = _nftId;
}
function readTask(uint _id) public view returns (uint, uint256, uint256) {
uint index = findIndex(_id);
return (tasks[index].id, tasks[index].stackAddress, tasks[index].nftId);
}
function deleteTask(uint _id) public {
uint index = findIndex(_id);
delete tasks[index];
}
}
You can return an array of structs:
function readAllTask() public view returns (Task[] memory) {
return tasks;
}
I think you have reason to do it, but just a remind that saving the data into blockchain is not a good deal, due to the high cost.
If you would like to return all the task, then simply make the tasks public. Solidity automatically assign a get function for it.
If you would like to get some specific content of task struct, then consider something like this:
function readAllTask() public view returns (uint, uint256, uint256 [] memory) {
// something
}
I'm trying to create a variable "project" to store data from a mapping but I get "Decalration error, undefined identifier" on project = projects[addr]
function getProjectInfo(address addr) public view returns (string memory name, string memory url, uint funds){
var project = projects[addr];
}```
Use explicit variable type definition:
pragma solidity ^0.5.8;
contract Test
{
struct Project
{
bytes32 name ;
}
mapping (address => Project) projects ;
constructor () public {
}
function getProjectInfo(address addr) public view returns (string memory name, string memory url, uint funds)
{
Project memory project = projects[addr];
// ...
}
}
I've tried creating a new crypto token with myetherwallet and it works, except the initial supply is incorrect. I've asked 100,000,000,000 and only got 1000,000 .
I setting the initial supply possible through myetherwallet or should I use Myst?
Here's how I created the contract:
in myst
pragma solidity ^0.4.8;
contract tokenRecipient { function receiveApproval(address _from, uint256
_value, address _token, bytes _extraData); }
contract ForCoin {
/* Public variables of the token */
string public standard = 'ForCoin 0.1';
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
/* This generates a public event on the blockchain that will notify clients
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/* This notifies clients about the amount burnt */
event Burn(address indexed from, uint256 value);
/* Initializes contract with initial supply tokens to the creator of the
contract */
function ForCoin(
uint256 initialSupply,
string tokenName,
uint8 decimalUnits,
string tokenSymbol
) {
initialSupply = 100000000000;
balanceOf[msg.sender] = initialSupply; // Give the creator
all initial tokens
totalSupply = initialSupply; // Update total
supply
name = tokenName; // Set the name for
display purposes
symbol = tokenSymbol; // Set the symbol
for display purposes
decimals = decimalUnits; // Amount of
decimals for display purposes
}
Copy code to myetherwallet and deploy.
Remark: I've also filled out the initial supply value in myst itself on the right hand side.
Thanks!
You must have given decimal places as 5.