原因
是一个function里面的变量 数量不能超过(16),包括了入参和返回值。
解决方法
- 减少方法内不必要的变量
- 使用结构体减少单个变量参数
是一个function里面的变量 数量不能超过(16),包括了入参和返回值。
某个基于EOS开发的链,提供了免费的账户注册接口,执行调用后,空投账户免费为其抵押CPU NET和购买RAM。由于接口没有做严格有效的防刷处理,导致账户注册严重超过预期,导致链内系统资源浪费严重,以及空投部分系统代币占用过多
一次性扩增RAM容量。(eosio->setram)
void system_contract::setram( uint64_t max_ram_size ) {
require_auth( get_self() );
check( _gstate.max_ram_size < max_ram_size, "ram may only be increased" ); /// decreasing ram might result market maker issues
check( max_ram_size < 1024ll*1024*1024*1024*1024, "ram size is unrealistic" );
check( max_ram_size > _gstate.total_ram_bytes_reserved, "attempt to set max below reserved" );
auto delta = int64_t(max_ram_size) - int64_t(_gstate.max_ram_size);
auto itr = _rammarket.find(ramcore_symbol.raw());
/**
* Increase the amount of ram for sale based upon the change in max ram size.
*/
_rammarket.modify( itr, same_payer, [&]( auto& m ) {
m.base.balance.amount += delta;
});
_gstate.max_ram_size = max_ram_size;
}
每块持续新增。(eosio->setramrate)
设置完每块新增量后
void system_contract::setramrate( uint16_t bytes_per_block ) {
require_auth( get_self() );
update_ram_supply();
_gstate2.new_ram_per_block = bytes_per_block;
}
当下次有购买内存的操作时,执行时间差内的容量扩增
void system_contract::buyram( const name& payer, const name& receiver, const asset& quant )
{
require_auth( payer );
update_ram_supply();
https://developers.eos.io/manuals/eosio.contracts/latest/key-concepts/ram
2016年 11月22日,Spurious Dragon硬叉推出了 EIP-170,该协议增加了24.576 kb的智能合约大小限制。对于您作为Solidity开发人员而言,这意味着当您向合同中添加越来越多的功能时,在某些时候您将达到极限,并且在部署错误时会看到以下错误:
Warning: Contract code size exceeds 24576 bytes (a limit introduced in Spurious Dragon). This contract may not be deployable on mainnet. Consider enabling the optimizer (with a low "runs" value!), turning off revert strings, or using libraries.
引入此限制是为了防止拒绝服务(DOS)攻击。任何签订合同的呼吁都是相对便宜的。但是,合约调用对以太坊节点的影响取决于被调用合约代码的大小(从磁盘读取代码,预处理代码,将数据添加到Merkle证明中)不成比例地增加。每当您遇到这种情况时,攻击者只需很少的资源即可为他人带来很多工作,那么您就有可能遭受DOS攻击。
最初,这没有什么问题,因为一个自然合同大小限制是块气限制。显然,需要在包含合同所有字节码的事务中部署合同。如果然后仅将一个事务包含在一个块中,则可以用尽所有气体,但是它不是无限的。但是,在这种情况下,问题在于阻气限值会随时间变化,并且在理论上是不受限制的。在EIP-170时,块气限制仅为470万。现在,区块气体限制上个月才再次增加到1190万。
对各个合约进行优化之前,我们要先知道各个合约各自的体积,Truffle -contract-size插件是帮助您的一个好工具,如果您使用的是Truffle
npm install truffle-contract-size
在truffle-config.js文件中加入
plugins: ["truffle-contract-size"]
Run truffle run contract-size
此时就可以看到各个合约的各自的体积了
这应该始终是您的第一种方法。您如何将合同分成多个较小的合同?通常,它会迫使您为合同设计出良好的体系结构。从代码可读性的角度来看,始终首选较小的合同。对于拆分合同,请问自己:
比如
function get(uint id) returns (address,address) {
MyStruct memory myStruct = myStructs[id];
return (myStruct.addr1, myStruct.addr2);
}
修改为
function get(uint id) returns (address,address) {
return (myStructs[id].addr1, myStructs[id].addr2);
}
相差0.28kb。您很可能会在合同中找到许多类似的情况,而这些情况实际上加起来可观。
比如
require(msg.sender == owner, "Only the owner of this contract can call this function");
修改为
require(msg.sender == owner, "OW1");
每次修改完,重新编译合约,然后查看优化大小,是否已到达临界内
开源地址:https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol
/// @dev Models a uint -> uint mapping where it is possible to iterate over all keys.
library IterableMapping
{
struct itmap
{
mapping(uint => IndexValue) data;
KeyFlag[] keys;
uint size;
}
struct IndexValue { uint keyIndex; uint value; }
struct KeyFlag { uint key; bool deleted; }
function insert(itmap storage self, uint key, uint value) returns (bool replaced)
{
uint keyIndex = self.data[key].keyIndex;
self.data[key].value = value;
if (keyIndex > 0)
return true;
else
{
keyIndex = self.keys.length++;
self.data[key].keyIndex = keyIndex + 1;
self.keys[keyIndex].key = key;
self.size++;
return false;
}
}
function remove(itmap storage self, uint key) returns (bool success)
{
uint keyIndex = self.data[key].keyIndex;
if (keyIndex == 0)
return false;
delete self.data[key];
self.keys[keyIndex - 1].deleted = true;
self.size --;
}
function contains(itmap storage self, uint key) returns (bool)
{
return self.data[key].keyIndex > 0;
}
function iterate_start(itmap storage self) returns (uint keyIndex)
{
return iterate_next(self, uint(-1));
}
function iterate_valid(itmap storage self, uint keyIndex) returns (bool)
{
return keyIndex < self.keys.length;
}
function iterate_next(itmap storage self, uint keyIndex) returns (uint r_keyIndex)
{
keyIndex++;
while (keyIndex < self.keys.length && self.keys[keyIndex].deleted)
keyIndex++;
return keyIndex;
}
function iterate_get(itmap storage self, uint keyIndex) returns (uint key, uint value)
{
key = self.keys[keyIndex].key;
value = self.data[key].value;
}
}
// How to use it:
contract User
{
// Just a struct holding our data.
IterableMapping.itmap data;
// Insert something
function insert(uint k, uint v) returns (uint size)
{
// Actually calls itmap_impl.insert, auto-supplying the first parameter for us.
IterableMapping.insert(data, k, v);
// We can still access members of the struct - but we should take care not to mess with them.
return data.size;
}
// Computes the sum of all stored data.
function sum() returns (uint s)
{
for (var i = IterableMapping.iterate_start(data); IterableMapping.iterate_valid(data, i); i = IterableMapping.iterate_next(data, i))
{
var (key, value) = IterableMapping.iterate_get(data, i);
s += value;
}
}
}
开源地址:https://github.com/apolonsoft/ethereum-event-explorer
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
python3 event_listener.py