Ethereum Developer Resources

OneSwap Series 2 - How to configure smart contracts

In the process of program development, we are often faced with the following requirements:
  1. Static configuration: The source code should be developed to be versatile for different purposes through simple configuration.
  2. Dynamic configuration: During the program operation, change the behavior of the program by modifying some preferences
This article offers suggestions on how to meet the static and dynamic configuration requirements when developing smart contracts using the Solidity language.

Static configuration through constants

Among the static configuration methods well known to programmers, the macro in C/C++ is the oldest. The preprocessor reads the source code with macro definitions and converts it into source code without macro definitions. Because of the lack of type information, macros are inherently inadequate, and thus may bring along security risks when used to define literal values and implement conditional compilation. As an alternative, constants should be used to realize literal values, and constants and if-else for effects similar to conditional compilation.
After learning the lessons of C/C++, many programming languages, such as Java, C# and Golang, no longer support macros and preprocessors. The Solidity language does not support macros or preprocessors, either ( Although a third-party preprocessor can be used to support macros, such as, that is a rare case in practice.
Solidity provides the constant keyword to define constantsknown at compile time (hereinafter referred to as constants). The use of constants does not involve storage operations at all. In the source code of OneSwap, the constant constant is frequently used for configuration. For example, in OneSwapPair.sol:
 string private constant _NAME = "OneSwap-Share"; uint8 private constant _DECIMALS = 18; 
In the code, the name of the ERC20 token is set by the constant_NAME, and the effective number of decimal places after the decimal point is set by_DECIMALS. As long as these constants are modified, the code can be applied to different occasions.

Static configuration through persistent storage

Configuration through constants requires modifying the source code and recompiling to get the new bytecode before deployment. Sometimes we find this method not flexible, and hope to decide the value of the configuration at the time of deployment. This can be achieved by assigning values to persistent storage in the constructor. If the value of "constant" can be determined only when the contract is deployed (for example, passed in through the constructor), it can only be achieved through ordinary state variables before Solidity v0.6.5. Below is a code in OneSwapToken.sol:
 mapping (address => uint256) private _balances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private immutable _decimals; constructor (string memory name, string memory symbol, uint256 supply, uint8 decimals) public OneSwapBlackList() { _name = name; _symbol = symbol; _decimals = decimals; _totalSupply = supply; _balances[msg.sender] = supply; } 
The state variables_name,_symbol, and_decimals here are all assigned values only once in the constructor, and they are read-only during subsequent operations.

Static configuration through Immutable

As we know, the reading and writing of the contract state, that is, the reading and writing of storage, consumes a lot of gas. Therefore, when writing a contract, we should do everything possible to reduce (preferably to eliminate) storage reading and writing. State variables that are written only once are too wasteful of gas. The state variable immutable newly added by Solidity in v0.6.5 optimizes the condition that "a constant, once assigned in the constructor, is read-only during the subsequent operation". By modifying the bytecode during contract runtime when deploying the contract, the "constant" can be determined until the contract is deployed. For the convenience of discussion, we call the state variable immutable as an invariable. In the examples listed above, _decimals is an invariable.

The underlying implementation mechanism of the three static configuration methods

Constants and ordinary state variables are easier to understand. Now we will compare constants, invariables and ordinary state variables through a case study to discuss the realization principle of invariables.
The invariables are easy to use: just add the keyword immutable when defining a state variable, and assign value to it in the constructor. Note that you can only and must assign a value to an invariable when the contract is constructed, and only its value can be read when the contract is executed. At present, invariables can only be used to define value types, not structures or other types. For example, in the above example, _name and_symbol cannot be defined immutable. However, this restriction may be released in future versions of Solidity. Now we use a simple example contract to analyze the principle of invariables. The complete code is as follows:
pragma solidity =0.6.12; contract ImmutableDemo { uint256 private constant _f0 = 0x1234; uint256 private immutable _f1 = 0x5678; uint256 private immutable _f2; uint256 private _f3; constructor(uint256 f2) public { _f2 = f2 & 0xABCD; _f3 = 0xEFEF; } function addF0(uint256 x) external pure returns (uint256) { return (x + _f0) & 0xFFFFFF00; } function addF1(uint256 x) external view returns (uint256) { return (x + _f1) & 0xFFFFFF01; } function addF2(uint256 x) external view returns (uint256) { return (x + _f2) & 0xFFFFFF02; } function addF3(uint256 x) external view returns (uint256) { return (x + _f3) & 0xFFFFFF03; } } 
The contract defines a total of 4 variables. Among them, _f0 is a known constant at compile time, _f1 and _f2 are invariables, and _f3 is an ordinary state variable. The value of _f1 is determined at compile time, and the value of _f2 is calculated through the parameters passed to the constructor when the contract is created. The value of _f3 is initialized when the contract is created. In addition to the constructor, the contract also defines 4 external methods. To facilitate the observation of the compiled bytecode of the contract, we used some special constants in these methods and performed simple calculations. In addition, the logic of these methods is very simple.
Compile the above contract using solc (v0.6.12), and we can get the contract bytecode. The complete contract bytecode is also called the creation bytecode of the contract. It is mainly divided into two parts. The first half is the bytecode executed when the contract is deployed, and the second half is the runtime bytecode of the contract. The constructor of the contract will be compiled to the first half and executed when the contract is deployed for such operations as contract state initialization. After the bytecode is created, the runtime bytecode of the contract will be returned.
Note that for the contract creation bytecode, the runtime bytecode is just normal data. The contract creation bytecode can return the runtime bytecode intact (directly on the chain), or it can be modified arbitrarily and then returned (for example, by injecting the actual value of the invariable. See below for details). For more information on the contract bytecode, please refer to this article, and for more information on contract deployment, please refer to this article.
The compiled bytecode (creation bytecode) of our sample contract totals 673 (0x2A1) bytes, as shown below:
The runtime code of the contract starts from the 134th (0x86) byte and totals 539 (0x21B) bytes, as shown below:
Below we will carefully analyze these two bytecodes to see how the invariables work.

Gas consumption of different configurations

Let's first look at the runtime bytecode of the contract. For the convenience of observation, the assembly code of the contract will be shown below. Long as the assembly code of the contract is, we can be sure that the logic of the constructor is not in the runtime bytecode according to the special constant value in the source code, and thus can easily find the assembly code of the four external methods. Most of the assembly code is omitted here, but only the important parts of the 4 external methods:
... [345] JUMPDEST [346] PUSH1 0x00 [348] PUSH4 0xffffff00 [353] PUSH2 0x1234 [356] DUP4 [357] ADD [358] AND ... [365] JUMPDEST [366] PUSH1 0x00 [368] PUSH4 0xffffff01 [373] PUSH32 0x0000000000000000000000000000000000000000000000000000000000000000 [406] DUP4 [407] ADD [408] AND ... [415] JUMPDEST [416] PUSH1 0x00 [418] PUSH4 0xffffff02 [423] PUSH32 0x0000000000000000000000000000000000000000000000000000000000000000 [456] DUP4 [457] ADD [458] AND ... [465] JUMPDEST [466] PUSH1 0x00 [468] PUSH4 0xffffff03 [473] PUSH1 0x00 [475] SLOAD [476] DUP4 [477] ADD [478] AND ... 
  1. PC (Programm Counter) is the assembly code of the addF0() function starting from 345, and the compile-time constants are compiled into PUSH2 instructions (PC is 353).
  2. The PC from 365 is the assembly code of the addF1() function. The invariable _f1 is compiled into PUSH32 instructions (PC is 373), and the immediate value is 0.
  3. The PC from 415 is the assembly code of the addF2() function. The invariable _f2 is also compiled into PUSH32 instructions (PC is 423), and the immediate value is 0.
  4. PC from 465 is the assembly code of the addF3() function, and ordinary state variables are compiled into SLOAD instruction (PC is 475).
It can be seen that in the runtime bytecode of the contract, the invariable is compiled into a PUSH instruction (the specific instruction depends on the number of bytes occupied by the invariable). But the immediate value of the instruction, which is 0, only serves as a placeholder. The creation bytecode of the contract must properly handle the immediate value of the PUSH instruction corresponding to each invariant, and replace it with the actual value, which will be further analyzed below.
Like constants, invariables are compiled into PUSH instructions, so they both consume the same gas, much lower than the gas consumed by ordinary state variables (SLOAD consumes 800 gas).

Implementation of immutable variables: Modify bytecode on the chain

Compared to the runtime bytecode of the contract, creation bytecode is a bit more complicated, so we need a form that facilitates observation. With the online disassembler provided by, we can disassemble the bytecode into a relatively easy-to-understand pattern. The following is the disassembly result of the contract creation bytecode:
contract disassembler { function main() public return () { mstore(0x40,0xC0); mstore(0x80,0x5678); var0 = msg.value; require(!msg.value); var1 = (code.size - 0x2A1); callcodecopy(0xC0,0x2A1,(code.size - 0x2A1)); mstore(0x40,((code.size - 0x2A1) + 0xC0)); require((0x20 < (code.size - 0x2A1))); temp0 = (0xC0 + var1); temp1 = mload(0xC0); mstore(0xA0,(temp1 & 0xABCD)); sstore(0x0,0xEFEF); temp3 = mload(0x80); temp2 = mload(0xA0); callcodecopy(0x0,0x86,0x21B); mstore(0x1A8,temp2); mstore(0x176,temp3); RETURN(0x0,0x21B); } } 
Compared with the bytecode and assembly code, it is already an improvement. Still hard to understand? Don't worry. We will add comments to the disassembly code above, remove the irrelevant code, rename some variables, and explain each line of code in detail.
 function main() public return () { mstore(0x40,0xC0); // m[0x40] = 0xC0 mstore(0x80,0x5678); // m[0x80] = 0x5678 require(!msg.value); 
Line 1 above: The compiler reserves 0xC0 bytes of memory, and records this number in memory 0x40. Line 2: Record 0x5678 in memory 0x80. Line 3 has nothing to do with the discussion in this article and can be ignored.
 argsLen = (code.size - 0x2A1); callcodecopy(0xC0,0x2A1,argsLen); // m[0xC0] = args mstore(0x40,(argsLen + 0xC0)); // m[0x40] = 0xC0 + argsLen require((0x20 < argsLen)); 
Line 1: When the contract is deployed, the parameters passed to the constructor (after ABI encoding) will be spliced behind the bytecode. We can obtain the total length of the code after adding the parameter with the CODESIZE instruction, and, after subtracting the real code length 0x2A1, get the length of the parameter. Line 2: Copy the incoming parameters to 0xC0 in the memory. Line 3: Update the number of memory usage. Line 4: Ensure the length of the incoming parameter is sufficient.
 f2 = mload(0xC0); // f2 = m[0xC0] mstore(0xA0,(f2 & 0xABCD)); // m[0xA0] = f2 & 0xABCD sstore(0x0,0xEFEF); // _f3 = 0xEFEF 
Line 1: Load the parameter f2 that has been loaded into the memory onto the operand stack. Line 2: Perform a bitwise AND operation between f2 and 0xABCD, and then record it in memory 0xA0. Line 3: Initialize the state variable_f3.
 _f1 = mload(0x80); // _f1 = m[0x80] = 0x5678 _f2 = mload(0xA0); // _f2 = m[0xA0] = f2 & 0xABCD callcodecopy(0x0,0x86,0x21B); // m[0x00:] = code[0x86: 0x86+0x21B] mstore(0x1A8,_f2); // m[0x01A8] = _f2 mstore(0x176,_f1); // m[0x0176] = _f1 RETURN(0x0,0x21B); } 
The first and second lines above load the values at memory 0x80 and 0xA0 onto the operand stack. These two temporary variables record the actual values of _f1 and _f2. Then the value previously placed in memory is completely useless, so on the third line all the runtime bytecodes are copied to memory 0. On Lines 4 and 5, the immediate placeholders of PUSH instructions of two invariables in the runtime bytecode (located at 0x0176 and 0x01A8 in the runtime bytecode, respectively) are replaced with actual values. At this point, the runtime bytecode is ready, and then returns on Line 6 through the RETURN instruction. The following is the complete disassembly code after being adjusted with comments:
contract disassembler { function main() public return () { mstore(0x40,0xC0); // m[0x40] = 0xC0 mstore(0x80,0x5678); // m[0x80] = 0x5678 require(!msg.value); argsLen = (code.size - 0x2A1); callcodecopy(0xC0,0x2A1,argsLen); // m[0xC0] = args mstore(0x40,(argsLen + 0xC0)); // m[0x40] = 0xC0 + argsLen require((0x20 < argsLen)); f2 = mload(0xC0); // f2 = m[0xC0] mstore(0xA0,(f2 & 0xABCD)); // m[0xA0] = f2 & 0xABCD sstore(0x0,0xEFEF); // _f3 = 0xEFEF _f1 = mload(0x80); // _f1 = m[0x80] = 0x5678 _f2 = mload(0xA0); // _f2 = m[0xA0] = f2 & 0xABCD callcodecopy(0x0,0x86,0x21B); // m[0x00:] = code[0x86: 0x86+0x21B] mstore(0x1A8,_f2); // m[0x01A8] = _f2 mstore(0x176,_f1); // m[0x0176] = _f1 RETURN(0x0,0x21B); } } 

Combining proxy mode and static configuration

As mentioned earlier, the value of the invariable is determined when the contract is constructed and injected into the runtime bytecode of the contract, so the gas consumed by the invariable reading during the contract runtime is the same as that consumed by the constant. OneSwap mainly includes 7 contracts, most of which use invariables. Take OneSwapPairProxy as an example:
contract OneSwapPairProxy { uint internal _unlocked; uint internal immutable _immuFactory; uint internal immutable _immuMoneyToken; uint internal immutable _immuStockToken; uint internal immutable _immuOnes; uint internal immutable _immuOther; constructor(address stockToken, address moneyToken, bool isOnlySwap, uint64 stockUnit, uint64 priceMul, uint64 priceDiv, address ones) public { _immuFactory = uint(msg.sender); _immuMoneyToken = uint(moneyToken); _immuStockToken = uint(stockToken); _immuOnes = uint(ones); uint temp = isOnlySwap ? 1 : 0; temp = (temp<<64) | stockUnit; temp = (temp<<64) | priceMul; temp = (temp<<64) | priceDiv; _immuOther = temp; _unlocked = 1; } receive() external payable { } fallback() payable external { /* code omitted */ } } 
Similar to Uniswap, OneSwap's Pair contract is created by the Factory contract. The difference is that OneSwap adopts a proxy model in order to minimize the gas consumption when a Pair is created. Considering the complex logic of Pair and the gas-consuming deployment, OneSwap puts this part of the logic in the OneSwapPair contract which needs to be deployed only once. The Factory deploys the OneSwapPairProxy contract each time, which forwards all actual operations to OneSwapPair for processing. With the proxy mode, OneSwap also supports the upgrade of the Pair logic. In addition, to benefit from both the invariable and proxy mode at the same time, the OneSwap project has also explored the "Immutable Forwading" mode, which we will specifically introduce in a follow-up article.

Dynamic configuration of the contract

Constants must be valued when the contract is compiled, and invariables must be valued when the contract is constructed. That is static configuration. Common state variables can be modified after contract deployment, which is dynamic configuration. It is advised to limit the modification of important configurations to privileged accounts or governance contracts only. For example, the maintenance of the mainstream token list of the BuyBack contract follows this mode, and the list can only be configured by the ONES issuer:
contract OneSwapBuyback is IOneSwapBuyback { mapping (address => bool) private _mainTokens; address[] private _mainTokenArr; ... // Other codes omitted function addMainToken(address token) external override { require(msg.sender == IOneSwapToken(ones).owner()); if (!_mainTokens[token]) { _mainTokens[token] = true; _mainTokenArr.push(token); } } function removeMainToken(address token) external override { require(msg.sender == IOneSwapToken(ones).owner()); if (_mainTokens[token]) { _mainTokens[token] = false; uint256 lastIdx = _mainTokenArr.length - 1; for (uint256 i = 0; i < lastIdx; i++) { if (_mainTokenArr[i] == token) { _mainTokenArr[i] = _mainTokenArr[lastIdx]; break; } } _mainTokenArr.pop(); } } } 
The feeBPS and pairLogic variables of the OneSwapFactory contract are configured through the OneSwapGov contract. The feeBPS variable is read by the OneSwapPair contract to control the fee rate. The pairLogic variable is read by the OneSwapProxy contract. This variable and dynamic configuration is a major contributor to the negligible gas consumed by the Pair deployment and upgradeable Pair logic of the OneSwap project.


This article summarizes the two configuration methods of smart contracts: static configuration and dynamic configuration, and introduces several protection modes of dynamic configuration: privilege modification mode and governance mode. Static configuration can be realized through constants and invariables, and dynamic configuration through ordinary state variables. It also goes deep into the implementation of invariables at the EVM bytecode level.
Before Solidity v0.6.5, the constant value that could be determined when the contract was constructed could only be expressed by the state variable of the contract. Writing state variables during contract creation requires considerable Gas, and reading state variables during contract execution also consumes a lot of Gas (compared to PUSH instructions of the constant). The immutable state variable introduced in Solidity v0.6.5 effectively solves this problem by modifying the contract runtime bytecode (replacing placeholders) when the contract is deployed. In OneSwap, we used immutable state variables as much as possible, and also explored the "Immutable Forwading" mode, which is one of the reasons for the low Gas consumption in OneSwap. In subsequent articles, we will introduce more details on the implementation of the OneSwap project.


submitted by OneSwap to defi [link] [comments]

Top 10 of the Best Tools for Blockchain Development

Top 10 of the Best Tools for Blockchain Development
Blockchain has completed its journey of a decade. In this span, despite facing a lot of resilience, technology has overcome all the challenges and become one of the leading technologies. As per Upwork, Blockchain was one of the fastest-growing skills in 2008. Knowing its importance and growth that it has to offer, many individuals are now opting for Blockchain courses. There are specified Blockchain courses for Blockchain developer, Blockchain engineer, and other associated profiles. You can pick the one you interest you and start the journey to become a successful blockchain developer. While you pick up the Blockchain training, it also becomes crucial that you must acquire the knowledge about Blockchain tools. In this blog, we will discuss ten different Blockchain tools that will help you become a proficient Blockchain developer.
Top 10 Blockchain tools:
1. Geth- The first tool that we are discussing here is Geth; it is an implementation of Ethereym node and is written in the Go programming language. It acts as a node for Ethereum Blockchain. One can easily mine token, transfer the tokens, and also create smart contracts using Geth.
2. Solidity- if you are planning to become an Ethereum expert, you must have expertise in Solidity. It is one of the most popular programming languages. It supports the OOP paradigm and is mostly used for writing smart contracts. Blockchain developers can use Solidity to write applications. It is useful in creating contracts for voting, multi-signature wallet, and blind auctions.
3. Mist- This is the official Ethereum wallet that is available on Windows, Mac, and Linux. One of the key things you must know about Mist is that once you have created the password for it, you have to remember it, as you cannot change it.
4. Solc- or Solidity Compiler is written in C++. It converts solidity scripts into a more readable format. The smart contracts written in Solidity must be converted into a format that can be easily read by the EVM, and here Solc comes into the picture.
5. Remix- It is a browser-based Blockchain tool. This is also used for the creation of smart contracts. This one is written in Javascript. It is used for testing, troubleshooting, and debugging the smart contracts written in Solidity.
6. Metamask- It is a wallet which acts as a connecting line between a browser and Ethereum Blockchain. It acts as a browser extension.
7. Truffle- It is an Ethereum Blockchain framework used to create a development environment for developing applications based on Ethereum. Blockchain developers can access a vast library. This is used for developing complex Ethereum dApps. It can also perform automated contract testing using Mocha and Chain.
8. Ganache- You can create a private Blockchain using this tool. This can be used to test dApps and execute commands.
9. Blockchain Testnet- Blockchain developers develop apps, but it’s important for them to check if the app is free from error or not, with the help of Blockchain Testnet, you can test the applications before making them go live. You can check for the bugs or other errors.
10. Blockchain-as-a-Service (BaaS)- This works similarly as that of SaaS. You can leverage cloud-based solutions to build and hose custom-made Blockchain applications.
Wrapping up-
These were some of the important Blockchain tools. If you are planning to enroll in Blockchain training, you must also develop expertise in using these tools. They will help in better implementation of technology.
Moreover, with the right set of skills, you also become eligible for a better Blockchain developer salary. Blockchain development is not just about learning the concepts. Still, it is also about implementing the concepts; Blockchain Council is the platform that will provide you all the information and knowledge about Blockchain courses. If you wish to become an expert Blockchain developer, Blockchain certification will give you the right direction.
submitted by Blockchain_org to BlockchainStartups [link] [comments]

Help test a new open source crowdfunding

So you think Ethereum is great, but how do you get started developing your app? Could you use it handle real money?
I'm releasing a new open source crowdfunding contract to raise 100 ETH for lean startup funding. It's a distributed seed funding model headed by Adam Berk. More importantly, it's a public learning experiment to teach anyone how to crowdfund with Ethereum.
I'm developing the contract in the open here for anyone who wants to use it:
You can follow the contract status here:
I'm currently testing this contract on Rinkeby. If you'd like to help me, please create a Rinkeby addresss, request some Rinkeby ETH from the faucet, and pay into the contract. You can follow thess write-ups here:
This test contract is set to expire on May 25th, 2017 at 0:00 EDT, or epoch time 1495684800
I'll send updates to this thread, and also tweet live updates to @InvisibleLearn. Soon I'll write up a blog post about my development process. Thanks for helping the Ethereum community!
submitted by cryptogoth to ethdev [link] [comments]

Getting Started with Ethereum Blockchain Development Ethereum BlockChain Tutorial - Compilation of Smart Contracts - Part2 Ethereum setup Windows 10 Intro To Smart Contracts in Ethereum, Learn About Solidity and the EVM in 6 mins Building and installing Ethereum compilers

Friends, From our team to you and yours, we hope everyone and their families are well and keeping safe during these complicated weeks. To help pass some time while we’re all stuck in doors, it’s time again to update the community on progress made by some of the EF-supported projects not covered in last week’s ESP Allocation Update.While the last Winter edition in this series was posted ... The assertion is clearly false, and an assertion failure warning should be returned.. Low-level API. The low-level API is as follows: solc.lowlevel.compileSingle: the original entry point, supports only a single file; solc.lowlevel.compileMulti: this supports multiple files, introduced in 0.1.6; solc.lowlevel.compileCallback: this supports callbacks, introduced in 0.2.1 A Python implementation of the Ethereum Virtual Machine Container. 100K+ Downloads. 0 Stars. ethereum/solidity-buildpack-deps Unfortunately, the official Ethereum documentation has not been updated to reflect the fact that compiling using the solC compiler is no longer possible via RPC. This means that you will end up in a rabbit hole if you try to follow the instructions on the official Ethereum documentation and many other tutorials based on official documentation. The following blog post is an analysis of 2019 data with the goal of sharing actionable insights for Ethereum users. Sources of the data are the block explorer, website analytics, and lists ...

[index] [4169] [3757] [992] [1661] [3116] [6255] [2414] [28] [4161] [3766]

Getting Started with Ethereum Blockchain Development

Our intention is to make new technologies & emerging tools installation easy for students, beginners & experienced professionals. 1. Ethereum Installation - ... Ethereum is a Proof-of-Work blockchain that allows users to build their own decentralised applications. iIt is a smart contract platform that supports a generalised scripting language. SolC and the browser-based compiler are the two most common compilers for Solidity. These compilers compile Solidity into EVM bytecodes, which can then be deployed into the Ethereum blockchain. Getting Started with Ethereum Blockchain Development this tutorial will show how to develop your own Blockchain environment with Ethereum by writing, deploy and test your first smart contract ... 1BestCsharp blog Recommended for you 44:14 3 Compile and run your first smart contract against local private node - Ethereum from scratch - Duration: 32:42.