Implement address(...).code in the IR

This commit is contained in:
chriseth 2020-12-10 14:37:26 +01:00 committed by Alex Beregszaszi
parent 7b347b9ec2
commit baaf7c0db8
5 changed files with 30 additions and 3 deletions

View File

@ -4055,3 +4055,21 @@ string YulUtilFunctions::copyConstructorArgumentsToMemoryFunction(
.render();
});
}
string YulUtilFunctions::externalCodeFunction()
{
string functionName = "external_code_at";
return m_functionCollector.createFunction(functionName, [&]() {
return util::Whiskers(R"(
function <functionName>(addr) -> mpos {
let length := extcodesize(addr)
mpos := <allocateArray>(length)
extcodecopy(addr, add(mpos, 0x20), 0, length)
}
)")
("functionName", functionName)
("allocateArray", allocateMemoryArrayFunction(*TypeProvider::bytesMemory()))
.render();
});
}

View File

@ -460,6 +460,11 @@ public:
std::string const& _creationObjectName
);
/// @returns the name of a function that copies code from a given address to a newly
/// allocated byte array in memory.
/// Signature: (address) -> mpos
std::string externalCodeFunction();
private:
/// Special case of conversion functions - handles all array conversions.
std::string arrayConversionFunction(ArrayType const& _from, ArrayType const& _to);

View File

@ -1622,6 +1622,12 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
"balance(" <<
expressionAsType(_memberAccess.expression(), *TypeProvider::address()) <<
")\n";
else if (member == "code")
define(_memberAccess) <<
m_utils.externalCodeFunction() <<
"(" <<
expressionAsType(_memberAccess.expression(), *TypeProvider::address()) <<
")\n";
else if (member == "codehash")
define(_memberAccess) <<
"extcodehash(" <<

View File

@ -12,8 +12,6 @@ contract C {
function g() public view returns (uint) { return address(0).code.length; }
function h() public view returns (uint) { return address(1).code.length; }
}
// ====
// compileViaYul: false
// ----
// constructor() ->
// initCode() -> 0x20, 0

View File

@ -13,7 +13,7 @@ contract C {
function g() public returns (uint) { return address(new A()).code.length; }
}
// ====
// compileViaYul: false
// compileViaYul: also
// ----
// f() -> 0x20, 0x20, 0x48aa5566000000
// g() -> 0x20