mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Provide access to the name of contracts.
This commit is contained in:
parent
1169004cec
commit
d2f493268b
@ -1,6 +1,7 @@
|
|||||||
### 0.5.5 (unreleased)
|
### 0.5.5 (unreleased)
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
|
* Meta programming: Provide access to the name of contracts via ``type(C).name``.
|
||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
@ -2154,6 +2154,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
|||||||
"Circular reference for contract code access."
|
"Circular reference for contract code access."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if (magicType->kind() == MagicType::Kind::MetaType && memberName == "name")
|
||||||
|
annotation.isPure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -340,7 +340,8 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess)
|
|||||||
{MagicType::Kind::Message, "data"},
|
{MagicType::Kind::Message, "data"},
|
||||||
{MagicType::Kind::Message, "sig"},
|
{MagicType::Kind::Message, "sig"},
|
||||||
{MagicType::Kind::MetaType, "creationCode"},
|
{MagicType::Kind::MetaType, "creationCode"},
|
||||||
{MagicType::Kind::MetaType, "runtimeCode"}
|
{MagicType::Kind::MetaType, "runtimeCode"},
|
||||||
|
{MagicType::Kind::MetaType, "name"},
|
||||||
};
|
};
|
||||||
set<MagicMember> static const payableMembers{
|
set<MagicMember> static const payableMembers{
|
||||||
{MagicType::Kind::Message, "value"}
|
{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();
|
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_typeArgument).contractDefinition();
|
||||||
if (contract.canBeDeployed())
|
if (contract.canBeDeployed())
|
||||||
return MemberList::MemberMap({
|
return MemberList::MemberMap({
|
||||||
{"creationCode", std::make_shared<ArrayType>(DataLocation::Memory)},
|
{"creationCode", make_shared<ArrayType>(DataLocation::Memory)},
|
||||||
{"runtimeCode", std::make_shared<ArrayType>(DataLocation::Memory)}
|
{"runtimeCode", make_shared<ArrayType>(DataLocation::Memory)},
|
||||||
|
{"name", make_shared<ArrayType>(DataLocation::Memory, true)},
|
||||||
});
|
});
|
||||||
else
|
else
|
||||||
return {};
|
return {};
|
||||||
|
@ -186,6 +186,11 @@ public:
|
|||||||
/// Stack post:
|
/// Stack post:
|
||||||
void memoryCopy();
|
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)
|
/// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true)
|
||||||
/// external function type <address><function identifier> into two stack slots:
|
/// external function type <address><function identifier> into two stack slots:
|
||||||
/// address (right aligned), function identifier (right aligned)
|
/// address (right aligned), function identifier (right aligned)
|
||||||
@ -285,11 +290,6 @@ private:
|
|||||||
/// Address of the precompiled identity contract.
|
/// Address of the precompiled identity contract.
|
||||||
static unsigned const identityContractAddress;
|
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.
|
/// Appends code that cleans higher-order bits for integer types.
|
||||||
void cleanHigherOrderBits(IntegerType const& _typeOnStack);
|
void cleanHigherOrderBits(IntegerType const& _typeOnStack);
|
||||||
|
|
||||||
|
@ -1361,6 +1361,18 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
|||||||
);
|
);
|
||||||
m_context << Instruction::POP;
|
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
|
else
|
||||||
solAssert(false, "Unknown magic member.");
|
solAssert(false, "Unknown magic member.");
|
||||||
break;
|
break;
|
||||||
|
@ -15113,6 +15113,55 @@ BOOST_AUTO_TEST_CASE(code_access_content)
|
|||||||
ABI_CHECK(callContractFunction("testCreation()"), encodeArgs(true));
|
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()
|
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