Where in the code and what is the proper way to add legal verbiage to my ERC20 Smart Contract?
I've seen a few samples where it gets saved on a variable and then that variable value is referenced in the body of a function using memory.
i.e.
contract MyToken is ERC20, Ownable {
string public processNumber = "0041518-41.1982.8.26.0053";
string public legalBinding = "a lot, a lot of verbiage would go here";
constructor() ERC20("MyToken", "MTK") {
_mint(msg.sender, 9000000 * 10 ** decimals());
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function setProcessNumber (string memory v) public onlyOwner() {
processNumber = v;
}
function setLegalBinding (string memory v) public onlyOwner() {
legalBinding = v;
}
}
What are those two last functions doing anyway does it ever get executed or just saved in memory?
Is that the correct practice?
Is there a better approach to this?
Where in the code do developers typically add that type of info?
If I'm to save a massive string of text containing all the legal verbiage. on a variable can I save those on a template literal using back-ticks to leverage multiple lines breaks inside the string and so forth?
I would like to go point-by-point to your question :
What are those two last functions doing anyway does it ever get executed or just saved in memory?
These functions are basically overriding the values of these variables, which in your case, are by default initialised at the very beginning of the contract. As we have the onlyOwner() modifier set on these functions, only the owner can change these variables by calling these methods explicitly, and by providing the necessary Gas cost.
Is that the correct practice? Kind-of, Yes
Is there a better approach to this?
The method can be modified to view restriction
Where in the code do developers typically add that type of info?
If you want the value to be a constant, i.e, it should not be changed through out the course of the contract, add the constant modifier. Additionally, you can add make the variable immutable, which means the initial constant value string can be avoided, and the variable can only be initialised with a constant value at first run, and then the value cannot be changed.
If I'm to save a massive string of text containing all the legal verbiage. on a variable can I save those on a template literal using back-ticks to leverage multiple lines breaks inside the string and so forth?
Yes, you can. Please refer here : https://docs.soliditylang.org/en/v0.8.0/internals/layout_in_storage.html?highlight=string
Hope that it helps!
Related
I'm having problems setting a value in a deployed BSC smart contract, below is the problematic solidity function, is the fact '_value' has been used not 'value' as the pass parameter ?
function setSwapTokensAtAmount(uint256 _value) external onlyOwner
{
swapTokensAtAmount = _value;
}
I have looked at other contracts and can't see any that use the '_' when labelling a pass parameter value, which can be used (from my understanding) denote a public or private variable.
It's a common practice to name function-scoped variables starting with underscore. But naming the variable with or without underscore doesn't have any effect on the resulting functionality.
I see that your function uses the onlyOwner modifier. While your code doesn't show the modifier implementation, we can assume that it controls that only authorized sender can execute the function.
So a very likely reason why you cannot update the variable is that you're trying to execute the function from a different address than the authorized owner.
I was wondering what information are publicly visible and intelligible when an EOA (external ownable address) calls a payable function on a smart contract, with some parameters and a return value.
Let us say I have the smart contract function below, the question is: 'is the return value visible somewhere on the blockchain?'. I am using Solidity 0.8.12.
function askForSecretCode(uint time) external payable returns (bytes32) {
require(msg.value == 42, 'Need to pay 42 wei.');
secretCodes[secretCodesNum] = keccak256(abi.encodePacked(msg.sender, time);
return keccak256(abi.encodePacked(msg.sender, time);
}
Anyone can see the input time param value as a part of a transaction invoking the askForSecretCode function.
Even though if you don't publish the contract source code, the bytecode is public, and there are decompilers that can (with some error rate) help generate source code back from the bytecode. So let's assume that the source code is available as well.
From the source code (or usually even from the pseudocode generated by the decompiler), anyone can determine the storage slot of secretCodesNum (which from the context seems to be a property of the contract) and retrieve its value using the eth_getStorageAt RPC method, including historical values.
Using these secretCodesNum values, they can use the same method to determine storage slots of any secretCodes[secretCodesNum] and their values.
TLDR: Never ever store private data on the blockchain.
I'm trying to create a "real" transaction from inside a smart contract to an EOA. This is so that I can attach data/input_data to send to it.
I've read several resources on this but I've come to contradictory information: some say it's impossible, some say that call() can achieve this. I've been testing multiple methods and have not come to see that it is possible.
Here's a simple example of what I'm trying to achieve:
pragma solidity 0.8.6;
contract Simple {
uint32 value;
constructor() payable {
// Contract is initialized with 0.5 ether
value = 22;
}
function foo() public {
require(address(this).balance >= 0.1 ether);
// Along with transfering ether, I want to send some data to the EOA,
// for example, whichever value is in the variable "value"
payable(msg.sender).transfer(0.1 ether);
}
}
On a "normal" transaction, it is possible to set the field "input data" (normally used to make function calls when sending a transaction to a smart contract), which allows us to send data on a transaction from an EOA to another EOA. I was able to achieve this already.
But, from my understanding, contracts "can't" create transactions; they only create "internal transactions" (informal name) that are associated with the "parent transaction" (transaction that called the contract in the first place) and therefore don't have the data field. But they're able to call another contract on the network, so I assume they're able to send some data along the network, right?
Furthermore, this question seems to imply that the low level call() method is able to achieve this. I've tried multiple approaches but have not been able to reproduce the wanted behaviour.
msg.sender.call{value: 0.1 ether}("data", value); // Doesn't work
msg.sender.call{value: 0.1 ether}(value); // Doesn't work
msg.sender.call{value: 0.1 ether}(abi.encodeWithSignature(value)) // Doesn't work
At some point, I did find my message on a block's "extra data", but from my understanding, this was written there by the miner for some reason.
So, to sum it up, is it possible to, from a contract, send ether + message to an EOA account? How would I achieve this?
Edit: Fixed the function name, which was a reserved keyword.
function msg() public {
This function name is a bit problematic, because you're overriding the global msg variable, and can't use the msg.sender.
So I changed the function name to generic foo().
function foo() public {
msg.sender.call{value: 0.1 ether}
Since Solidity 0.8, an address is not payable by default (source: docs). So if you want to send them the native currency (in case of Ethereum, that's ETH), you need to cast the address to payable first.
payable(msg.sender).call{value: 0.1 ether}
Finally to the data sending part.
At some point, I did find my message on a block's "extra data", but from my understanding, this was written there by the miner for some reason.
I'm not exactly sure, but it seems like you stumbled upon the correct field, which is simply the data field of the raw transaction, and the blockchain explorer probably named it "extra data". The data field is not filled by the miner, but by the transaction creator.
Since you're sending an integer, and the data field is bytes (array of bytes), you need to encode it to bytes. In your case:
abi.encode(value)
To you put it all together:
pragma solidity 0.8.6;
contract Simple {
uint value;
constructor() payable {
value = 22;
}
function foo() public {
require(address(this).balance >= 0.1 ether);
payable(msg.sender).call{value: 0.1 ether}(abi.encode(value));
}
}
When you execute the foo() function (and the contract has enough funds), it will create an internal transaction (some blockchain explorers might use a different name) to the msg.sender with value 0.1 ether and the decimal 22 encoded as hex 16 in the data field.
I have a field in my contract. It's something like this:
contract MyContract {
string private secretField
}
function getSecretField() public view returns {
... some controls here...
return secretField;
}
I want to reach that secretField from my backend server and protect it from any other requester. What is the best practice for this?
If it's on a public blockchain (mainnet, ropsten testnet, ...), it's always going to be accessible by querying the storage slot containing the secretField value from an off-chain app. No matter the Solidity private visibility modifier because the storage query is performed on a lower layer.
Example: If secretField is the first property of the first defined contract (on this address), its value is stored in storage slot 0.
But if you only want to hide it from on-chain requesters, you can keep the property private and require the getter to be accessed only from a certain address.
// removed `view` because it's going to interact with the transaction data
function getSecretField() public returns {
// reverts if the sender address is not 0x123
require(msg.sender == address(0x123);
return secretField;
}
Note that your backend app is going to have to send a transaction from the 0x123 address in order to access the data. Simple call won't return anything because the getSecretField() is not a view function anymore.
After a stumbled upon this question I thought about how I would define a pure function. I have two rules to accept a function as pure which somewhat differ from the definition cited in the top answer. I'm interested to know if my view is correct or not.
My "2 rules" are:
The function will not change the state of the program.
The input is constant for the same arguments or the same local public program state.
To clarify the second point, by local public state I mostly mean public class members. Local means that the state is strongly associated with the function and is exclusive to it (ie. not some global variables).
My reasoning for using that definition is that it is just a more expanded view (perhaps too specific to CS) on the term arguments, as I see local public state being only a different interface for passing function arguments.
Is this definition acceptable or is the inclusion of a class context destroys the "prunes" of the function?
Edit: As an example for what I mean consider the following class (C++).
class Foo
{
public:
int Number;
int foo(int v) { return Number + v; }
}
Considering that an instance function call is actually the following call:
foo(&this, 123)
How is this different from passing the public data (Number) via a struct?
struct Foo
{
int Number;
}
foo(Foo { 1 }, 123);
No, that "or the same local public program state" is not in the pure method definition everyone else agrees with.
A pure function computes a value based on the input parameters and the input parameters alone, and does not, beyond returning the computed value, produce any observable side effects.
I advice you to take a look at the Wikipedia page on Pure function as it shows some examples.
--
Also note that "no observable side effects" does not mean "no side effects whatsoever", but the gray area overlapping those two generally only include runtime-specific side effects that you have no control over and generally do not observe.
This also includes state such as "there is enough memory to allocate the memory needed".