i'm using the ECR721 preset smart contract from Openzeppelin for studying.
I would like to add a new field when i mint new token to store a string (public).
At the moment there is only the field "to:address" (screenshot below)
I'm sure i need to add something in the mint function:
Easiest way to store the message on blockchain is to emit an event. Event is permanently stored and publicly readable.
Define new MintMessage event outside the mint() function. I don't recommend expanding the default Transfer event that is used during minting, because external tools (such as Etherscan) might ignore the non-standard event and not show minted tokens as a result.
Add a new argument to the mint() function
Emit the MintMessage event within the mint() function
event MintMessage(string message);
function mint(address to, string message) public virtual {
// keep the rest of your function as is
// add a new line emiting the event to the end of the function
emit MintMessage(message);
}
Related
In solidity, while relating a "withdraw" function to be only callable from the admin contract, the "construct" comes handy.
address public owner;
constructor() public { owner =msg.sender;}
Question: How come it has to be set as a "public" function? As we want no one but us to trigger the withdraw, shouldn´t it be entered as "internal" or "private"?
the constructor is just triggered on deploy so no one else can call it before the deploy, it can be public and you will have no problems but in most recent solidity versions is not necessary to mark the constructor as public
A withdraw function should be marked as public or external for you, or its non-contract owner, to be able to withdraw it. Why? If you mark a function as private, only the functions inside the smart contract will be able to interact with it, and by marking a function as internal, functions inside a contract and contracts that inherit from this one will be able to call the function. Why you probably want to make it this way? Because you, as a normal user, wont be able to call this function directly. So by making this function public or external, every user will be able to interact with the function. And here is your question.
How come it has to be set as a "public" function? As we want no one but us to trigger the withdraw, shouldn´t it be entered as "internal" or "private"?
You can set the function as public and create a require statement (it can be a modifier or a conditional "if", as you want.) and just check if the remitent is the owner. And only if it is, then withdraw. Here is an example:
function withdraw() public {
require(msg.sender == owner, "Only the owner can call this function.");
// Withdraw logic here.
}
Hope you find this useful :)
PluginUtilities is documented as "Functionality for Flutter plugin authors.". It's quite hard to understand what it does. When/ how should I use it?
PluginUtilities does two things:
You can pass these references between completely different isolates running different code. For example, you could implement a method in Isolate A, get a handle for it, pass the handle to Isolate B, get the method from that handle using PluginUtilities.getCallbackHandle, and call that method in Isolate B.
final handle = PluginUtilities.getCallbackHandle(myLovelyFunctionTearOff); // What is a tear off?: https://stackoverflow.com/questions/69065771/what-is-an-instance-method-tear-off
if (handle == null) {
// function has to be a static method or a top level function. It is null otherwise.
// TODO Show an error to the user to help them fix it.
}
Once you receive the handle in a separate isolate, you can get the function once again:
final function = PluginUtilities.getCallbackFromHandle(handle);
final result = function();
Examples of usage
Firebase messaging uses it twice, specifically for background messages. They use it for 2 functions:
They get a handle to the users callback function, that the user set.
final CallbackHandle userHandle = PluginUtilities.getCallbackHandle(handler)!;
They get a handle to their additional app entrypoint (main function, which they call _firebaseMessagingCallbackDispatcher ):
final CallbackHandle bgHandle = PluginUtilities.getCallbackHandle(_firebaseMessagingCallbackDispatcher)!;
They save these handles into SharedPreferences, and use them when the app is launched by a push notification. This is because the Flutter application doesn't automatically get launched in this case, on Android. The service or broadcast receiver is launched without an Activity, which launches the FlutterEngine and your app.
When this happens, Firebase_messaging will use these handles to get the callback function and app entrypoint, and launch them. So your callback still gets called when the your app is not running, because it runs a new application/ entrypoint (_firebaseMessagingCallbackDispatcher):
void _firebaseMessagingCallbackDispatcher() {
// Initialize state necessary for MethodChannels.
WidgetsFlutterBinding.ensureInitialized();
const MethodChannel _channel = MethodChannel(
'plugins.flutter.io/firebase_messaging_background',
);
// This is where we handle background events from the native portion of the plugin.
_channel.setMethodCallHandler((MethodCall call) async {
/** implementation of method call handling **/
});
// Once we've finished initializing, let the native portion of the plugin
// know that it can start scheduling alarms.
_channel.invokeMethod<void>('MessagingBackground#initialized');
I am trying to save a variable that gets emmited by an event, from a function in another smart contract, that I’m calling, into a storage variable within my smart contract.
So my call looks something like this:
ExternalContract.foo(boo);
The event in ExternalContract that contains the desired variable:
emit Event(bytes desiredVariable)
So I want to save this variable in my contract without relying on an off-chain script. Is there even a way to do it?
The Log and its event data is not accessible from within contracts (not even from the contract that created them).
Source: https://docs.soliditylang.org/en/v0.8.7/contracts.html#events
So unless there's a getter function for the desiredVariable, or unless it's stored in a public property (they have automatically generated getter functions as well), there's no way to get the event log value from a contract, and you'll need to use an off-chain app.
I am new to solidity, but checking through a specific contract I found the following line of code in the IERC20 declaration:
IERC20 public "TOKEN NAME" = IERC20("THE ADDRESS OF ANOTHER CONTRACT");
This code was found in a contract that is effectively a fork of another project, but the developers say they are unrelated. Of course, people are just FOMO into the token - I know this forum here is not for this type of discussion so I'll abstain from the same.
However, from a solidity coding perspective, why would one write this line of code directly referencing another contract address (the forked address) when making the IERC20 declaration - what does this do, is there a purpose to this?
It seems to me that this is easier and more reliable. Alternatively, you can pass this address in constructor parameters, or provide a special method to set it.
The IERC20 is an interface that defines expected functions arguments and return values.
It helps validating whether the caller is passing correct data types, amount of arguments, and helps parsing the returned data to expected types.
Let's show it on a very simple interface
interface IGame {
function play(uint256 randomNumber) returns (bool won);
}
Elsewhere in your contract, you define a variable that uses this interface
IGame game = Game("0xthe_game_address");
You can then directly call the other contract's methods defined in the interface and pass the return values to your variables.
bool didIWin = game.play(1);
The call would fail if the game contract didn't have the play method or didn't return any value (plus in few other cases).
As for why is the address hardcoded, it's probably just to simplify the development as Mad Jackal already said in their answer.
One more plausible reason in some cases is to gain more trust by showing users that the contract admins are not able to cheat you by changing the destination address (possibly to a contract made by them doing whatever they want).
Edit: If the another contract's address is really unrelated and useless (meaning, the fork is not calling it), it's probably just a human error and the developer forgot to remove it.
I'm a programming noob and didn't quite understand the concept behind callback methods. Tried reading about it in wiki and it went over my head. Can somebody please explain this in simple terms?
The callback is something that you pass to a function, which tells it what it should call at some point in its operation. The code in the function decides when to call the function (and what arguments to pass). Typically, the way you do this is to pass the function itself as the 'callback', in languages where functions are objects. In other languages, you might have to pass some kind of special thing called a "function pointer" (or similar); or you might have to pass the name of the function (which then gets looked up at runtime).
A trivial example, in Python:
void call_something_three_times(what_to_call, what_to_pass_it):
for i in xrange(3): what_to_call(what_to_pass_it)
# Write "Hi mom" three times, using a callback.
call_something_three_times(sys.stdout.write, "Hi mom\n")
This example let us separate the task of repeating a function call, from the task of actually calling the function. That's not very useful, but it demonstrates the concept.
In the real world, callbacks are used a lot for things like threading libraries, where you call some thread-creation function with a callback that describes the work that the thread will do. The thread-creation function does the necessary work to set up a thread, and then arranges for the callback function to be called by the new thread.
Wiki says:
In computer programming, a callback is
a reference to executable code, or a
piece of executable code, that is
passed as an argument to other code.
This allows a lower-level software
layer to call a subroutine (or
function) defined in a higher-level
layer.
In common terms it is the mechanism to notify a piece of code i.e. a method, which piece of code to execute, i.e. another method, when it is needed.
Callback is related to the fact that the client of the calling function specifies a function that belongs to the client code's responsibility to the calling function to execute and this is passed as an argument.
An example is in GUIs. You pass as argument the function to be called once an event occurs (e.g. button pressed) and once the event
occurs this function is called.
This function is usually implemented by the object that originally registered for the event
Callback function is a function that is called through a function pointer. If you pass the pointer (address) of a function as an argument to another, when that pointer is used to call the function it points to it is said that a call back is made.
Why Should You Use Callback Functions?
A callback can be used for notifications. For instance, you need to set a timer in your application. Each time the timer expires, your application must be notified. But, the implementer of the time'rs mechanism doesn't know anything about your application. It only wants a pointer to a function with a given prototype, and in using that pointer it makes a callback, notifying your application about the event that has occurred. Indeed, the SetTimer() WinAPI uses a callback function to notify that the timer has expired (and, in case there is no callback function provided, it posts a message to the application's queue).
In general you supply a function as a parameter which gets called when something occurs.
In C code you will pass something that looks like this:
int (callback *)(void *, long );
meaning a function that takes two parameters, void * and long and returns an int.
With object-orientated languages the syntax is sometimes simpler. For example you might be able to construct a callback mechanism that allows the user to pass in an object that looks like a function or has an abstract method (thus wrapping a function) and context data too.
Modern languages use the term "delegate" to refer to a function "pattern". These can be used as callbacks. Some languages also use the term lambda which is essentially a function with no name, often created "on the fly" in a block of code and passed as a callback.
C++11 has introduced these into its standard.
The advantage of using a callback is that you can separate out, i.e. reduce / decouple an API from what is calling it, and to some extent vice versa, i.e. although in one place you know you are calling into the API, at the point of the "handler" it does not need to know from where it was called.
For example, you can have an API that generates objects and then "calls-back" as they get generated.
Call back means that you pass the code as a parameter. For example, imagine a button, that much show a dialog when pressed:
Button testBtn;
testBtn.setOnClickListener(new OnClickListener() {
#Override
public void onCLick() {
JOptionPane.showDialog(testBtn, "Test button pressed");
}
}
Here we tell the button what to execute, when it will be click. So, the framework will execute the passed code, when it detecs the click. Inside the framework there are some code like:
void processEvent(Event e) {
if (e.type == Event.CLICK) {
e.getComponent().getOnClickListener().onClick();
}
}
So, some basic code calls back the listener when the appropriate event happens.
PS: Pseudocode here, just do describe the idea.
A callback method is a method that gets called when an event occurs
In simple word, actually, a Callback is a reference to a function or method, which you can pass as a parameter to another function for calling it back later.
From the above figure, B_reference() is the callback method.
Source code sample:
>>> def A(A_msg,B_reference):
... # After printing message, method B is called.
... print(A_msg)
... B_reference()
...
>>> def B():
... print("Message from B")
...
>>>
>>> A("Message from A",B)
Message from A
Message from B
>>>
If you still don't understand what it is, you can check this video: