mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6097 from ethereum/meta-name
Provide access to the name of contracts.
This commit is contained in:
commit
da7139afc5
@ -1,6 +1,7 @@
|
||||
### 0.5.5 (unreleased)
|
||||
|
||||
Language Features:
|
||||
* Meta programming: Provide access to the name of contracts via ``type(C).name``.
|
||||
|
||||
|
||||
Compiler Features:
|
||||
|
@ -2154,6 +2154,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
||||
"Circular reference for contract code access."
|
||||
);
|
||||
}
|
||||
else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "name")
|
||||
annotation.isPure = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -340,7 +340,8 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
|
||||
{MagicType::Kind::Message, "data"},
|
||||
{MagicType::Kind::Message, "sig"},
|
||||
{MagicType::Kind::MetaType, "creationCode"},
|
||||
{MagicType::Kind::MetaType, "runtimeCode"}
|
||||
{MagicType::Kind::MetaType, "runtimeCode"},
|
||||
{MagicType::Kind::MetaType, "name"},
|
||||
};
|
||||
set<MagicMember> static const payableMembers{
|
||||
{MagicType::Kind::Message, "value"}
|
||||
|
@ -3490,8 +3490,9 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const
|
||||
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_typeArgument).contractDefinition();
|
||||
if (contract.canBeDeployed())
|
||||
return MemberList::MemberMap({
|
||||
{"creationCode", std::make_shared<ArrayType>(DataLocation::Memory)},
|
||||
{"runtimeCode", std::make_shared<ArrayType>(DataLocation::Memory)}
|
||||
{"creationCode", make_shared<ArrayType>(DataLocation::Memory)},
|
||||
{"runtimeCode", make_shared<ArrayType>(DataLocation::Memory)},
|
||||
{"name", make_shared<ArrayType>(DataLocation::Memory, true)},
|
||||
});
|
||||
else
|
||||
return {};
|
||||
|
@ -186,6 +186,11 @@ public:
|
||||
/// Stack post:
|
||||
void memoryCopy();
|
||||
|
||||
/// Stores the given string in memory.
|
||||
/// Stack pre: mempos
|
||||
/// Stack post:
|
||||
void storeStringData(bytesConstRef _data);
|
||||
|
||||
/// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true)
|
||||
/// external function type <address><function identifier> into two stack slots:
|
||||
/// address (right aligned), function identifier (right aligned)
|
||||
@ -285,11 +290,6 @@ private:
|
||||
/// Address of the precompiled identity contract.
|
||||
static unsigned const identityContractAddress;
|
||||
|
||||
/// Stores the given string in memory.
|
||||
/// Stack pre: mempos
|
||||
/// Stack post:
|
||||
void storeStringData(bytesConstRef _data);
|
||||
|
||||
/// Appends code that cleans higher-order bits for integer types.
|
||||
void cleanHigherOrderBits(IntegerType const& _typeOnStack);
|
||||
|
||||
|
@ -1361,6 +1361,18 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
);
|
||||
m_context << Instruction::POP;
|
||||
}
|
||||
else if (member == "name")
|
||||
{
|
||||
TypePointer arg = dynamic_cast<MagicType const&>(*_memberAccess.expression().annotation().type).typeArgument();
|
||||
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*arg).contractDefinition();
|
||||
m_context << u256(contract.name().length() + 32);
|
||||
utils().allocateMemory();
|
||||
// store string length
|
||||
m_context << u256(contract.name().length()) << Instruction::DUP2 << Instruction::MSTORE;
|
||||
// adjust pointer
|
||||
m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
|
||||
utils().storeStringData(contract.name());
|
||||
}
|
||||
else
|
||||
solAssert(false, "Unknown magic member.");
|
||||
break;
|
||||
|
@ -15113,6 +15113,55 @@ BOOST_AUTO_TEST_CASE(code_access_content)
|
||||
ABI_CHECK(callContractFunction("testCreation()"), encodeArgs(true));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(contract_name)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
string public nameAccessor = type(C).name;
|
||||
string public constant constantNameAccessor = type(C).name;
|
||||
|
||||
function name() public pure returns (string memory) {
|
||||
return type(C).name;
|
||||
}
|
||||
}
|
||||
contract D is C {
|
||||
function name() public pure returns (string memory) {
|
||||
return type(D).name;
|
||||
}
|
||||
function name2() public pure returns (string memory) {
|
||||
return type(C).name;
|
||||
}
|
||||
}
|
||||
contract ThisIsAVeryLongContractNameExceeding256bits {
|
||||
string public nameAccessor = type(ThisIsAVeryLongContractNameExceeding256bits).name;
|
||||
string public constant constantNameAccessor = type(ThisIsAVeryLongContractNameExceeding256bits).name;
|
||||
|
||||
function name() public pure returns (string memory) {
|
||||
return type(ThisIsAVeryLongContractNameExceeding256bits).name;
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
bytes argsC = encodeArgs(u256(0x20), u256(1), "C");
|
||||
ABI_CHECK(callContractFunction("name()"), argsC);
|
||||
ABI_CHECK(callContractFunction("nameAccessor()"), argsC);
|
||||
ABI_CHECK(callContractFunction("constantNameAccessor()"), argsC);
|
||||
|
||||
compileAndRun(sourceCode, 0, "D");
|
||||
bytes argsD = encodeArgs(u256(0x20), u256(1), "D");
|
||||
ABI_CHECK(callContractFunction("name()"), argsD);
|
||||
ABI_CHECK(callContractFunction("name2()"), argsC);
|
||||
|
||||
string longName = "ThisIsAVeryLongContractNameExceeding256bits";
|
||||
compileAndRun(sourceCode, 0, longName);
|
||||
bytes argsLong = encodeArgs(u256(0x20), u256(longName.length()), longName);
|
||||
ABI_CHECK(callContractFunction("name()"), argsLong);
|
||||
ABI_CHECK(callContractFunction("nameAccessor()"), argsLong);
|
||||
ABI_CHECK(callContractFunction("constantNameAccessor()"), argsLong);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
5
test/libsolidity/syntaxTests/metaTypes/name.sol
Normal file
5
test/libsolidity/syntaxTests/metaTypes/name.sol
Normal file
@ -0,0 +1,5 @@
|
||||
contract Test {
|
||||
function f() public pure returns (string memory) {
|
||||
return type(Test).name;
|
||||
}
|
||||
}
|
4
test/libsolidity/syntaxTests/metaTypes/name_constant.sol
Normal file
4
test/libsolidity/syntaxTests/metaTypes/name_constant.sol
Normal file
@ -0,0 +1,4 @@
|
||||
contract C {
|
||||
string public constant name = type(C).name;
|
||||
}
|
||||
// ----
|
@ -0,0 +1,10 @@
|
||||
contract Test {
|
||||
function f() public pure returns (string memory) {
|
||||
return type(C).name;
|
||||
}
|
||||
}
|
||||
|
||||
contract C {
|
||||
function f() pure public {
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user